There are two issues with your attempt:
your array construction has an erroneous comma, which makes the first pattern token_a,
instead of token_a
<(printf '%s\n' "${grep_ignore[@]}")
is being passed to grep -v
as a file to be searched a pattern consisting of the process substitution's file descriptor string like /dev/fd/63
1, rather than as a list of patterns - to have patterns read from a file (or process substitution) you need to make it an argument to the -f
option
Correcting for these:
grep_ignore=("token_a" "token_b")
then
$ grep -rnw . -e "token2" | grep -vFf <(printf '%s\n' "${grep_ignore[@]}")
./file_token_c.txt:1:token2 token3
(the -F
says to treat the array elements as fixed strings rather than regular expressions).
Alternatively, at least in GNU grep, you can use --exclude
(and --include
) to limit the match to specific file subsets to avoid the second grep altogether. So using your example above:
$ grep -rnw . -e "token2"
./file_token_a.txt:1:token1 token2
./file_token_c.txt:1:token2 token3
but given an array of filename patterns (note the elements are separated by whitespace not commas):
grep_ignore=("*token_a*" "*token_b*")
then
$ grep -rnw . -e "token2" "${grep_ignore[@]/#/--exclude=}"
./file_token_c.txt:1:token2 token3
where the array parameter expansion ${grep_ignore/#/--exclude=}
expands as follows:
$ printf '%s\n' "${grep_ignore[@]/#/--exclude=}"
--exclude=*token_a*
--exclude=*token_b*
Alternatively you could use a brace expansion instead of an array:
grep -rnw . -e "token2" --exclude={"*token_a*","*token_b*"}
try it with set -x
for example:
$ grep -rnw . -e "token2" | grep -v <(printf '%s\n' "${grep_ignore[@]}")
+ grep --color=auto -rnw . -e token2
+ grep --color=auto -v /dev/fd/63
++ printf '%s\n'
./file_token_a.txt:1:token1 token2
./file_token_c.txt:1:token2 token3
Note how the grep command has become grep --color=auto -v /dev/fd/63
? You can further confirm that it's treating /dev/fd/63
as a pattern rather than a pseudo-file as follows:
printf '%s\n' /dev/fd/{61..65} |
grep -v <(printf '%s\n' "${grep_ignore[@]}")
(you'll see that /dev/fd/63
gets filtered out).
– Bruno Peixoto Dec 25 '22 at 23:08grep_ignores=( "*node_modules*" "*.git*" "*package-lock*" "*codecov*" "*scripts*" )
grep -rnw . -e "@babel/cli" | grep -vFf <(printf '%s\n' "${grep_ignores[@]}")
grep -vFf
togrep -vEf
. It worked like a charm! – Bruno Peixoto Dec 25 '22 at 23:10