shell expansion (A|B) in filenames?

The standard file name globbing pattern to match a digit is [0-9]. This matches a single digit:

cat file[0-9].txt

To select only two of these:

cat file[25].txt

For larger numbers than 9, brace expansion will be useful (but see note below for the difference between globbing patterns and brace expansions):

cat file{25..60}.txt

Again, brace expansion allows for individual numbers as well:

cat file{12,45,900,xyz}.txt

(note that in the example above, the brace expansion does not involve an arithmetic loop, but just generates names based on the strings provided).

In bash, with the extglob shell option enabled (shopt -s extglob), the following will also work:

cat file@(12|45|490|foo).txt

The @(...) pattern will match any one of the included |-delimited patterns.


The difference between globbing patterns as [...] and @(...) and brace expansions, is that a brace expansion is generated on the command line and may not actually match any existing names in the current directory. A filename globbing pattern will match names, but the shell won't complain if not all possible name exist. If no matching name exists, the pattern will remain be unexpanded, unless also the nullglob shell option is set, in which case the pattern is removed.

Example:

touch file1

ls file[0-9]

Here, only the file listing for file1 will be shown.

With ls file{0..9}, ls would complain about not finding file0, file2 etc.

In the following example, the first command will only touch existing names that matches the given pattern, while the second line will create files that does not already exist:

touch file[0-9]

touch file{0..9}

The syntax to use is file{1,2} which will evaluate to file1 and file2.

$ ls
$ touch file{1,2,3,4,5,6,7,8,9}
$ ls
file1  file2  file3  file4  file5  file6  file7  file8  file9

As Inian pointed out below as well ... it would be easier to do touch file{1..9} in this example case ...

$ ls
$ touch file{1..9}
$ ls
file1  file2  file3  file4  file5  file6  file7  file8  file9

You can also use multiple expressions, like:

$ ls
$ touch file{1..9}{a..z}
$ ls
file1a file1b file1c
[...]
file9x file9y file9z

Yes, the above will create 234 (9 times 26) files.


Yes you can use brace expansion in the bash shell. For just the couple of files just do file{1..2} or just as file{1,2}

Or if you are worried about the files not being there in some cases, just do a simple loop,

for file in file{1..4}.txt; do
    [ -f "$file" ] || continue
    echo "$file" # Do other actions on file here
done

Or if just concatenating is your only operation on the files and if you are unsure which files could not be present at any point of time, just cat them and suppress the errors. Re-directing standard error to /dev/null would suppress the errors if the file is not available.

cat file{1,5}.txt 2>/dev/null

or use the glob expression file[15] which does not complain about the errors if the file was not found.

cat file[15].txt