2

I have a find command:

find Directory/{Alpha,Bravo,Charlie} arg1 arg2

I want to replace Alpha,Bravo,Charlie with $find_dir

find Directory/{$find_dir} arg1 arg2

however the latter expands to

find Directory/{Alpha,Bravo,Charlie} arg1 arg2

rather then

find Directory/Alpha Directory/Bravo Directory/Charlie arg1 arg2

Why? It's part of a fairly complex bash script that may have more or less directories, not all which are relevant (so globbing Upload/* would not work). So if I setup three now and add another, I'll have to manually add it in later. Plus I need it run from the root of directories to keep finds outputs perspective (./Upload/Dir/file as opposed to ./Dir/file).

But using a variable would permit me to change that as needed and keep it relevant to other parts of the script.

jimmij
  • 47,140
Miati
  • 3,150

1 Answers1

5

From bash documentation, Brace Expansion section:

Brace expansion is performed before any other expansions, and any characters special to other expansions are preserved in the result. It is strictly textual. Bash does not apply any syntactic interpretation to the context of the expansion or the text between the braces. To avoid conflicts with parameter expansion, the string ‘${’ is not considered eligible for brace expansion.

Another note, in bash:

The order of expansions is: brace expansion, tilde expansion, parameter, variable, and arithmetic expansion and command substitution (done in a left-to-right fashion), word splitting, and filename expansion.

So in your case, bash saw brace expansion before variable expansion, it will do brace expansion first, produce result {Alpha,Bravo,Charlie}.

If you can control $find_dir variable content, you can use eval:

eval "find Directory/{$find_dir} arg1 arg2"
cuonglm
  • 153,898
  • That did the ticket. it successfully evaluated and works fine. You changed your post and removed what I found most helpful to understanding the issue (although you reiterated it) --> The order of expansions is: brace expansion; tilde expansion, parameter and variable expansion, arithmetic expansion, and command substitution; word splitting; and pathname expansion. – Miati Oct 29 '14 at 02:22
  • 1
    @Miati: I think the documentation in brace expansion section is more concise, because it has and any characters special to other expansions are preserved in the result. For The order of expansions is: brace expansion; tilde expansion, parameter and variable expansion, arithmetic expansion, and command substitution, you missed the important thing, they are done from left to right. You can try a=1; echo $a $((a++)) {0..$a} and see the result. If brace expansion was done first, you must get 1 1 1, but the result is 1 1 2. – cuonglm Oct 29 '14 at 02:30
  • @Miati: Sorry for mistyping in above comment, must get 1 1 {0..1}, but the result is 1 1 {0..2} – cuonglm Oct 29 '14 at 02:39