9

I am using linux and the following version of the bash:

GNU bash, version 5.1.16(1)-release (x86_64-pc-linux-gnu)

When I type:

echo file{[1,2],3}.txt

I expect brace expansion to be done first, so:

echo file[1,2].txt file3.txt

After that, I expect it to stop there, since [1,2] is not a valid globbing. However, it gives the following as output:

file[1.txt file2].txt file3.txt

Why?

List of files in current directory (result of ls command):

go.mod  hello.sh  hi  main.go
2
  • 2
    The files in the current directory do not play a role in your question. Commented Feb 22 at 16:52
  • 1
    @terdon I wonder what (if-any) change to question votes would be, if the "up/down vote arrows" were always on-screen rather than scrolling off the top as the viewer reads down through all the answers. Commented Feb 22 at 22:35

1 Answer 1

19

Because you are telling it to :) This is what bash sees:

file{[1,2],3}.txt

The [ and ] have no special meaning in this context, globs aren't expanded within brace expansions: if a brace expansion results in a glob, that glob would be evaluated by the shell after the brace expansion.

So here, what happens is that the shell sees three comma separated elements in the brace: [1, 2] and 3. This is why it duly prints out file[1.txt, file2].txt and file3.txt. It's no different than using something like file{a,b,c}.txt.

You can see it happening with set -x:

$ set -x
$ echo file{[1,2],3}.txt
+ echo 'file[1.txt' 'file2].txt' file3.txt
file[1.txt file2].txt file3.txt

This behavior is documented in the EXPANSIONS section of man bash where the order of precedence is given:

The order of expansions is: brace expansion; tilde expansion, parameter and variable expansion, arithmetic expansion, and command substitution (done in a left-to-right fashion); word splitting; and pathname expansion.

As an aside, [1,2] is a perfectly valid globbing pattern, it just isn't expanded inside the braces. For example:

$ touch file{1,2,3}.txt
$ ls
file1.txt  file2.txt  file3.txt
$ ls file[1,2].txt
file1.txt  file2.txt

Note that in globs, [a,b] matches any of the characters a, , or b. It doesn't mean "a or b".

3
  • 1
    @Yakog See also echo file{[1\,2],3}.txt. Commented Feb 22 at 14:02
  • @Kusalananda I got file[1,2].txt file3.txt. It looks like now , is not treated as a separator? Commented Feb 22 at 14:05
  • 2
    @yakog, Yes, escaping or quoting protects the comma from brace expansion. Try also something like touch file,.txt; ls file{[1\,2],3}.txt; ls file{"[1,2]",3}.txt . The first one should glob, while the second shouldn't, unless there's some difference between Bash versions (I only tried with 3.2). Commented Feb 22 at 14:09

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.