If you want to match and count (filenames), then ...
You might not need grep
at all for such task ... You can include and exclude filename patterns with find
s -name "..."
to include and ! -name "..."
to exclude ... You can nest as many as you need of these to match only the filenames you want e.g. like so:
find -type f -name "*foo*.sh" ! -name "*+*.sh"
This will output files with .sh
extension that have foo
and don't have +
in their names.
So your command substitution set parameter(Notice: ALL CAPS are used for shell's built-ins ... So use lower or mixed case for your parameters) would be:
count=$(find -maxdepth 1 -type f -name "*foo*.sh" ! -name "*+*.sh" | wc -l)
Notice .
(current working directory) is find
s default search path ... So you don't have to specify it.
If you want to match and count (text inside each file), then ...
You might not need any of that at all ... But, you'll, probably, need a more sophisticated tool other than grep
to do exactly the rather complex task of yours ... You can use only awk
with the shell's filename globbing like so:
awk '{for ( i=1; i <= NF; i++ ) { if ( $i !~ "+" ) { if ( $i == "foo" ) { count++ }} else { nextfile }}} END { print count }' *.sh
for ( i=1; i <= NF; i++ )
will pass each single field("word") in the current line on its own to the next action where if ( $i !~ "+" )
will check if the field doesn't contains the +
character(e.g. the field is not +
, foo+bar
, +foo
or foo+
) and if true, pass it to the next action where if ( $i == "foo" )
will check if the field is exactly foo
and if true, increment the counter using count++
or else
it will exit the current file and move on to processing the next file(passed to awk
in the file/s argument/s) using nextfile
and at the END
will print the value of the current counter(total for all processed files) using print count
.
And your command substitution set parameter(Use printf
instead of print
to avoid injecting a newline into the parameter) would be:
count=$(awk '{for ( i=1; i <= NF; i++ ) { if ( $i !~ "+" ) { if ( $i == "foo" ) { count++ }} else { nextfile }}} END { printf "%d", count }' *.sh)
This should work fine even if you run it on thousands of files ... If, however, your files are in tens of thousands or more and you get Argument list too long
error message, then, IMHO, you need to reconsider including such a task altogether in your script and find a different approach for achieving your goal.