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