Reputation: 5029
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.
Upvotes: 2
Views: 305
Reputation: 5029
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
Upvotes: 2
Reputation: 5982
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.
Upvotes: 1
Reputation: 1823
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 ~]#
Upvotes: 1
Reputation: 11216
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'
Upvotes: 1