bash asterisk variable substitution
Hi
I want to pass a mask to a bash program and have the find-command use this mask. Of course the mask will contain asterisks and I'm going nuts trying to find a combination of characters that will work. I'll skip by all the code and just show you what I'm finding when I type at the command prompt: # cd /tmp # mkdir dir1 dir2 dir3 # cd /home # find /tmp /tmp /tmp/dir1 /tmp/dir2 /tmp/dir3 Looks good. Now let's call find with an undefined (blank) switch. # find /tmp $switch_str /tmp /tmp/dir1 /tmp/dir2 /tmp/dir3 Looks good. Now let's call find with the name-switch. # find /tmp -name "*2*" /tmp/dir2 Looks good. Now let's define a mask variable and use it with the name-switch. # mask='*2*' # echo "$mask" *2* # find /tmp -name "$mask" /tmp/dir2 Looks good. Now let's combine the mask and the switch. This is where I run into trouble. # echo "$mask" *2* # switch_str="-name \"$mask\"" # echo "$switch_str" -name "*2*" # find /tmp $switch_str Now I get zero results. I also tried # switch_str="-name '$mask'" # echo "$mask" -name '*2*' # find /tmp $switch_str Same thing, I get nothing. BTW - I don't understand why the variable 'mask' was expanded even though it was in single quotes. I thought single quotes prevent expansion. Anyway... I don't understand it. When I echo the variables they look perfectly normal. You might notice that when I echo the variables, I put quotes around them. If I try and put quotes around them in the find command I get this: # echo "$switch_str" -name "*2*" # find /tmp "$switch_str" find: unknown predicate `-name "*2*"' Just in case you're wondering what I'm trying to do in this script. If a mask is passed to the script, then I define the switch_str script. If no mask is passed, then the switch_str script remains undefined. That way, I can put this switch_str variable on the find command and it should either perform the name function, or just do nothing as it is blank. I could make 2 separate find commands and have an if statement to choose one or the other, but I have a bunch of switches and a bunch of find commands to handle. I would prefer one find command and have a bunch of switches that are either active or blank. So I'm lost. Any help would be appreciated, Thanks. |
You have switch_str which contains literal asterisks. But when you pass it to the find unquoted, obviously asterisks are expanded. Try using shell arrays ..
declare -a arg arg[0]="-name" arg[1]="test*" find "${arg[@]}" |
That worked great, thanks.
The array-thing is a whole new area of bash programming with which I was not familiar (until now). I'm sure you're right about the asterisks expanding. I'm not looking for any further answer here (I'm good now), but I must remark that I'm still perplexed as to why the asterisks were expanding. If I echo the variable, it looks normal with no expansion. I can even put the entire find command with the switches and asterisks inside one variable, and it will run properly if I just type that variable at the command prompt. But if I try to just put the switch in a variable, something funny happens. |
When you want to get a deeper understanding, you can read man bash (on expansions) and info bash. The general idea is following: there are some expansions that always occur if a string is in specific context.
echo "$mask" -> echo "*2*" (stop, as * is inside "") echo *2* -> something2 echo $mask -> echo *2* -> something2 (as now * is not inside *) echo *2* (stops right here) Another question is argument count.. "a b" is one argument, while a b gets split into two arguments. @ is an exception in a sense - when used as index it allows "-enclosed string to get expanded to multiple arguments. |
All times are GMT -5. The time now is 06:44 AM. |