If your filenames don't contain newlines, you can avoid multiple invocations of grep
by having grep print the names of matching files, and count the results.
local IFS=$'\n' # inside a function. Otherwise use some other way to save/restore IFS
matches=( $(grep -lw "$users" "$file1" "$file2") )
The number of matches is "${#matches[@]}"
.
There might be a way to use grep --null -lw
here, but I'm not sure how to parse the output. Bash var=( array elements )
don't have a way to use a \0
delimiter instead of \n
. Maybe bash's mapfile
builtin can do it? But probably not, because you specify the delimiter with -d string
.
You could count=$(grep -l | wc -l)
, but then you have two external processes so you might as well just run grep
on the two files separately. (The difference between grep
vs. wc
startup overhead is small compared to fork+exec + dynamic linker stuff to start up a separate process at all).
Also, with wc -l
you don't find out which file matched.
With the results captured in an array, that might already be what you want, or if there's exactly 1 match, you can check if it was the first input or not.
local IFS=$'\n' # inside a function. Otherwise use some other way to save/restore IFS
matches=( $(grep -lw "$users" "$file1" "$file2") )
# print the matching filenames
[[ -n $matches ]] && printf 'match in %s\n' "${matches[@]}"
# figure out which input position the name came from, if there's exactly 1.
if [[ "${#matches[@]" -eq 1 ]]; then
if [[ $matches == "$file1" ]];then
echo "match in file1"
else
echo "match in file2"
fi
fi
$matches
is shorthand for ${matches[0]}
, the first array element.