12

When you use brace expansion in bash, something like

echo {a,b,c}

becomes

echo a b c

Is there a way to expand it to 3 separate commands, one for each expansion, instead?

So that:

echo {a,b,c}

would become

echo a
echo b
echo c
13

Is this just a "because I wanna know" question, or is there a real use case for it? We could go through some gymnastics to get it done:

$ eval echo\ {a,b,c}\;
a
b
c

But I'd hunt down anyone that was putting in these kinds of obfuscatory commands into our system scripts.

Why not go for clarity instead:

$ for X in {a,b,c}; do echo $X; done

You could even go whole-hog and put in a couple of newlines and indent it a bit so that you'd always be able to understand what you were trying to do.

5
  • 4
    @peth - I'm assuming this is a simplified example. If it is indeed as simple as a list, then you're right. If it's something more like file-{r,b,g}{m,n,o}{x,y.z}.foo then it's better to use the short form than enumerating all 27 value. – unpythonic Jul 1 '11 at 4:15
  • @peth - I thought it was a good follow-up question. – unpythonic Jul 1 '11 at 4:34
  • i've wanted to know this for a long time, thanks ! :) – Sirex Jul 1 '11 at 13:02
  • 1
    Well, the use case was programs that don't accept more than one file (for instance), so where the expansion wouldn't work. Therefore, it'd be nice to be easily able to just run the program multiple times. The for works for this, but it's still more typing :P – houbysoft Jul 2 '11 at 3:51
  • I used it to cleanup multiple git branches: eval git branch -d \{ branch-a, branch-b }\; – Kit Oct 8 '17 at 20:31
3

Based on Mark Mann's selected answer, I was able to further derive this example, which works great:

$ eval echo\ category_{17,32,33}.properties\{,.bak\}\;
category_17.properties category_17.properties.bak
category_32.properties category_32.properties.bak
category_33.properties category_33.properties.bak

What that is showing, is when you are using multiple occurrences of brace expansion within a line, Mark's original example would have printed every variation individually. Instead, I wanted to use his answer to move/rename multiple files. To ensure that the output matched the format that mv normally expects (mv oldfilename newfilename), I escaped the second occurrence of brace expansion, so that it wouldn't be evaluated until after the initial eval command had executed.

As the above output appeared as expected, I was then able to run the following command:

$ eval mv\ category_{17,32,33}.properties\{,.bak\}\;
$ ls
category_17.properties.bak  category_32.properties.bak  category_33.properties.bak

Many thanks to Mark for his original answer. Please up-vote his answer if you like what his answer allowed me to do :-)

1
$ echo {a,b,c} | xargs -n1
a
b
c
1
  • Notes: (1) If the command in question was other than echo, then we would need to supply it to xargs explicitly (e.g. echo {a,b,c} | xargs -n1 cowsay). (2) xargs interprets quotes and backslashes. The behavior doesn't matter in this simple case, but in general it does. // +1 anyway. – Kamil Maciorowski Sep 29 '20 at 16:32
0
printf '%s\n'  echo{\ a,\ b,\ c}
1

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.