A. Gille
A. Gille

Reputation: 1048

Parameter expansion not working in "find -exec"

I'm writing a bash script as above, but the parameter expansion is not working with the EXC variable.

#!/bin/bash
EXC="--exclude='*.js' --exclude='*.sh'"
find /path -exec grep ${EXC} "xxx" {} \; >> result.txt

Options in the EXC variable are not used by the grep call as it still parse JavaScript files...

Also tried

find /path -exec grep $EXC "xxx" {} \; >> result.txt

Upvotes: 0

Views: 709

Answers (5)

Mustafa DOGRU
Mustafa DOGRU

Reputation: 4112

these could help you;

#!/bin/bash
EXC="--exclude='*.js' --exclude='*.sh'"
find  /path -exec echo "grep ${EXC} 'xxx' {}" \; | bash > result.txt

or

#!/bin/bash
EXC="*js,*sh"
find  /path -exec echo "grep --exclude={${EXC}} 'xxx' {}" \; | bash  > result.txt

Upvotes: 0

chepner
chepner

Reputation: 531135

The problem is that the single quotes are not removed from the parameter expansion, so grep is receiving '*.js' as the pattern, not *.js as you want. You need to use an array to hold the arguments:

exc=( "--exclude=*.js" "--exclude=*.sh" )  # No single quotes needed
find /path -exec grep "${exc[@]}" "xxx" {} \; >> result.txt

The quoted parameter expansion prevents *.js and *.sh from being expanded by the shell in the same way that quoting them when used literally does. --exclude='*.js' and '--exclude=*.js' would both result in the same argument being passed to grep, as would the minimalist --exclude=\*.js. You could also define your array as

exc=( --exclude "*.js" --exclude "*.sh" )

since the long option and its argument can be specified as one word containing = or as two separate words.

Upvotes: 0

F4240
F4240

Reputation: 148

The problem is that i'm using a variable to hold some arguments, and parameter expansion does not replace the ${} thing by its value in the command line...

You can launch a subshell wich will perform what you want

#!/bin/bash
EXC="--exclude='*.js' --exclude='*.sh'"
find /path -exec bash -c "grep ${EXC} 'xxx' {}" \; >> result.txt

Upvotes: 0

Alberto Re
Alberto Re

Reputation: 514

It still parses or it's only applied by find also on files that you are trying to exclude?

Anyway, why not use only grep -r instead of find plus grep?

grep -r --exclude='*.js' --exclude='*.sh' "xxx" /path

Upvotes: 0

SLePort
SLePort

Reputation: 15461

You can filter find results with ! (not) operator combined with -name option. To exclude .js and .sh files:

find . -type f ! -name '*.js' ! -name '*.sh' -exec grep xxx  {} \;

Upvotes: 1

Related Questions