Bash brace expansion doesn't work in an export statement

Consider the following example:

$ echo file_{a,b,c}
file_a file_b file_c         # brace expansion worked :)

$ export VARIABLE=file_{a,b,c}
$ echo $VARIABLE
file_c                       # brace expansion didn't work :(

How come that if I echo file_{a,b,c} directly, the brace expansion prints the name of all three files, while if I assign the same expression to a variable and echo that, it only prints the name of file_c?

And is there a different way to assign a brace-expanded string to a variable that would work in my case?

Asked By: Thomas Fritz

||

Run it with set -x to see what happens:

$ set -x
$ export VARIABLE=file_{a,b,c}
+ export VARIABLE=file_a VARIABLE=file_b VARIABLE=file_c
+ VARIABLE=file_a
+ VARIABLE=file_b
+ VARIABLE=file_c

You end up assigning the different values to the same variable, and each overrides the earlier value.

I think brace expansion only works in a "list context", so it’s hard to use it for generating a single string. Unless with something like string=$(echo file_{a,b,c}).

If you do the same without export, i.e. VARIABLE=file_{a,b,c} it just assigns the unexpanded value, same as VARIABLE='file_{a,b,c}'. But if you do export VARIABLE=$foo, then $foo does not get word-split. Those assignment-builtins like export, and readonly etc. are a bit odd. (This is in Bash, that is. I didn’t test other shells.)

But, note that a space-separated string (if that’s what you’re thinking anyway) is not an optimal way to store distinct values, mostly since you can’t store e.g. filenames that themselves contain spaces.

If you can, and it depends on what you’re doing, you might want to consider using an array instead.

$ arr=( file_{a,b,c} )
$ echo "${arr[1]}"
file_b
$ printf "<%s>n" "${arr[@]}"
<file_a>
<file_b>
<file_c>
Answered By: ilkkachu
Categories: Answers Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.