S_Mindcore S_Mindcore - 14 days ago 5
Linux Question

How to use curly braces in a shell (bash)

I'm currently trying to reproduce basic shell behaviours, and more specifically globbing behaviours.
I was testing commands with curly braces in it and found this behaviour that I don't understand.
First, the content of the directory I'm working in is the following :

1abc 2abc 3abc abc1 abc2 abc3


Then, I typed the following command :
ls {[1-3],[a-c]}*
, and it returned me all the files above as expected.

And finally, I tried this command :
ls {{,[1-3]},[a-c]}*
, which as you can see, has imbricated curly braces. Now what I don't understand is the return of this command, because it gave me this :
1abc 1abc 2abc 2abc 3abc 3abc abc1 abc1 abc2 abc2 abc3 abc3


As you can see, all the files were returned two times, and I can't figure out how the shell is interpreting this.

I hope my explanation was clear.

Answer

The string {{,[1-3]},[a-c]}* is an expression interpreted as brace expansion that consists of the following patterns:

  • "emptiness" ({,),
  • [1-3], and
  • [a-c].

The * character (meaning "every filename in the given directory") is applied for each of them:

*       => 1abc  2abc  3abc  abc1  abc2  abc3
[1-3]*  => 1abc  2abc  3abc
[a-c]*  => abc1  abc2  abc3

The fact that you have nested the expressions doesn't change the meaning that it is just a list of the three patterns. The same effect could be achieved with a simpler expression like {,[1-3],[a-c]}*, or another "list of lists" like {,{[1-3],[a-c]}}*.

If you pass the expression to echo, it will print all the characters from the lines above, one after another:

$ echo {{,[1-3]},[a-c]}*
1abc 2abc 3abc abc1 abc2 abc3 1abc 2abc 3abc abc1 abc2 abc3

But ls sorts the entries alphabetically by default:

$ ls {{,[1-3]},[a-c]}*
1abc  1abc  2abc  2abc  3abc  3abc  abc1  abc1  abc2  abc2  abc3  abc3
Comments