How to expand 2nd argument if it's a glob pattern?

299 views Asked by At

I'm trying to write a script that counts the number of matches of some pattern in a list of files and outputs its findings. Essentially I want to call the command like this:

count-per-file.sh str_needle *.c

and get output like:

Main.c: 12
Foo.c: 1

The script:

#!/bin/bash
# Count occurences of pattern in files.
#
# Usage:
#   count-per-file.sh SEARCH_PATTERN GLOB_EXPR
for file in "$2"; do
    count=$(grep -a "$1" "$file" | wc -l)
    if [ $count -gt 0 ]; then
        echo "$file: $count"
    fi
done

The problem is if I call it like so I don't know how to loop over the file list, so this outputs nothing:

count-per-file.sh str_needle *.c

I found this answer but it deals the glob pattern being the only argument to the script, whereas in my script the first argument is the search pattern, and the rest are the files expanded from the glob.

4

There are 4 answers

2
DBedrenko On BEST ANSWER

As suggested I used shift which seems to 'pop' the first argument. Here's my working script:

#!/bin/bash
# Count occurences of pattern in files.
#
# Usage:
#   count-per-file.sh SEARCH_PATTERN GLOB_EXPR
search_pattern="$1"
shift

for file in "$@"; do
    count=$(grep -aiE "$search_pattern" "$file" | wc -l)
    if [ $count -gt 0 ]; then
        echo "$file: $count"
    fi
done
0
cms On

You can use substring parameter expansion with an start index like this to skip the first n-1 values in $@

"${@:n}"

e.g.

for FILE in "${@:2}" 
do
  echo $FILE
done

N.B. Your script doesn't get a 'glob pattern' as the second argument. The shell that calls your script expands the glob to a space separated list of files before your script sees it and passes this to your script as the parameter list. This is why you can use standard substring range expansion.

2
123 On

I think this is what you want

#!/bin/bash
# Count occurences of pattern in files.
#
# Usage:
#   count-per-file.sh SEARCH_PATTERN GLOB_EXPR
for file in $2; do                               #UNQUOTE THIS TO EXPAND GLOB
    count=$(grep -a "$1" "$file" | wc -l)
    if [ $count -gt 0 ]; then
        echo "$file: $count"
    fi
done

Then pass the glob in in quotes so it doesn't expand on the command line

count-per-file.sh str_needle '*.c'
0
Sriharsha Kalluru On

You can add the quotes while passing *.c and remove quotes while using them in for loop and it will work..

[root@client1 ~]# cat  count-per-file.sh
#!/bin/bash
# Count occurences of pattern in files.
#
# Usage:
#   count-per-file.sh SEARCH_PATTERN GLOB_EXPR
for file in $2; do
    count=$(grep -a "$1" $file | wc -l)
    if [ $count -gt 0 ]; then
        echo "$file: $count"
    fi
done
[root@client1 ~]# bash count-per-file.sh str_needle "*.c"
file.c: 1
Main.c: 12
[root@client1 ~]#