Bash – Why arguments in braces do not expand in this case

bashbrace-expansioncommand line

For example, I want to put some file names inside braces for expansion like this:

$ ls
blue_texture  blue_waves  green_light
$ ls -m | tr -d ' \n'
blue_texture,blue_waves,green_light 
$ echo foo/bar/{`ls -m | tr -d ' \n'`}
foo/bar/{blue_texture,blue_waves,green_light}

My question why doesn't brace expansion work here? I expected it to work as following:

$ echo foo/bar/{blue_texture,blue_waves,green_light}
foo/bar/blue_texture foo/bar/blue_waves foo/bar/green_light

Best Answer

The reason this does not work is because bash performs brace expansion before command substitution (the Bash Reference Manual has some information about this). The substitution is not performed until after the brace expansion already occurred.

The only way you could do this is by using eval, but do not do that in this case, as you will allow arbitrary command execution.

Instead you have to seek some other method. This should produce the output you seek:

for file in *; do
    printf '%s ' "foo/bar/$file"
done; echo
Related Question