简体   繁体   中英

find command argument -iname doesn't work from variable

find command argument -iname doesn't work from script when it's being used in a variable

iname="-iname '*py'"
echo iname:   $iname

doesn't work:

find . $iname -exec grep "text" {} \; 

works:

find . -iname '*py' -exec grep "text" {} \; 

EDIT

Solution:

I followed @chepner's explanation, and did this in my real-world script (it's more readable than using arrays from my perspective)

inamecmd=-iname
inamearg=*py
find . $inamecmd $inamearg -exec grep "text" {} \; 

etc.

When you type it out in full:

find . -iname '*py' -exec grep "text" {} \; 

bash uses the single quotes to recognize that you want to pass the literal string *.py as an argument to find . It then removes the single quotes; find does not see them.

When you use a variable:

iname="-iname '*py'"
find . $iname -exec grep "text" {} \; 

bash expands $iname to the literal string -iname '*py' , but does not remove the single quotes. find receives the literal string '*py' as an argument, so only matches files starting with a single quote and ending with py' .

Quoting the expansion of iname wouldn't help:

find . "$iname" -exec grep "text" {} \;

This time, find would receive as a single argument the string -iname '*py' , rather than two separate arguments -iname and '*py' . bash only performs one round of quote removal; it does not do so again on the result of the parameter expansion.

The correct way to pass multiple arguments to a command in a single variable is to use an array:

iname=(-iname "*py")
find . "${iname[@]}" -exec grep "text" '{}' \;

You can just use bash -c :

bash -c "find . $iname -exec grep "text" {} \;" 

OR better use BASH arrays :

iname=("-iname" "*sh")
find . "${iname[@]}" -exec grep "text" {} \;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM