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.
The string {{,[1-3]},[a-c]}*
is an expression interpreted as brace expansion that consists of the following patterns:
{,
),[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