4.8. Filename Expansion
Another way to save time in your commands is to use special characters to abbreviate filenames. You can specify many files at once by using these characters. This feature of the shell is sometimes called "globbing ."
The Windows command-line interpreter offers a few crude features of this type. You can use a question mark to mean "any character" and an asterisk to mean "any string of characters." Unix provides these wildcards too, but in a more robust and rigorous way.
Let's say you have a directory containing the following C source files:
$ ls inv1jig.c inv2jig.c inv3jig.c invinitjig.c invpar.c
To list the three files containing digits in their names, you could enter:
$ ls inv?jig.c inv1jig.c inv2jig.c inv3jig.c
The shell looks for a single character to replace the question mark. Thus, it displays inv1jig.c, inv2jig.c, and inv3jig.c, but not invinitjig.c because that name contains too many characters.
If you're not interested in the second file, you can specify the ones you want using brackets:
$ ls invjig.c inv1jig.c inv3jig.c
If any single character within the brackets matches a file, that file is displayed. You can also put a range of characters in the brackets:
$ ls inv[1-3]jig.c inv1jig.c inv2jig.c inv3jig.c
Now we're back to displaying all three files. The hyphen means "match any character from 1 through 3, inclusive." You could ask for any numeric character by specifying 0-9, and any alphabetic character by specifying [a-zA-Z]. In the latter case, two ranges are required because the shell is case-sensitive. The order used, by the way, is that of the ASCII character set.
Suppose you want to see the init file, too. Now you can use an asterisk because you want to match any number of characters between the inv and the jig:
$ ls inv*jig.c inv1jig.c inv2jig.c inv3jig.c invinitjig.c
The asterisk actually means "zero or more characters," so if a file named invjig.c existed, it would be shown too.
Unlike the Windows command-line interpreter, the Unix shells let you combine special characters and normal characters any way you want. Let's say you want to look for any source (.c) or object (.o) file that contains a digit. The resulting pattern combines all the expansions we've studied in this section:
$ ls *[0-9]*.[co]
Filename expansion is very useful in shell scripts (programs), where you don't always know exactly how many files exist. For instance, you might want to process multiple log files named log001, log002, and so on. No matter how many there are, the expression log* will match them all.
Again, zsh goes a bit further than the other shells. With zsh, you can look for certain files in the current directory and all subdirectories thereof, using ** as the directory specification. If we repeat the previous example of searching for certain C source files, but this time want to find them in the whole tree, the command would look like this:
$ ls **/inv?jig.c inv1jig.c inv2jig.c inv3jig.c old/inv1jig.c old/veryold/inv1jig.c