While most users learn shell pattern matching behavior early in their exposure to UNIX, it is useful to review it here before introducing the functions that implement it.
A shell pattern can consist of normal characters and meta-characters. Normal characters represent themselves, and meta-characters have a special meaning for pattern matching. The set of meta-characters for shell patterns is relatively small. They are
* | Star (asterisk) |
? | Question mark |
[ and ] | Square brackets |
! | Bang (in []) |
- | Hypen (in []) |
Backslash |
Each meta-character is described in the subsections that follow.
The * character can match zero or more characters. The following shell experiment on a FreeBSD system illustrates this meta-character at work:
$ cd /etc $ ls -l hosts.* -rw-r--r-- 1 root wheel 2278 Dec 20 1999 hosts.allow -rw-r--r-- 1 root wheel 115 Dec 20 1999 hosts.equiv -rw-r--r-- 1 root wheel 103 Dec 20 1999 hosts.lpd $
The shell matches all files that begin with hosts. and are followed by zero or more characters. Consequently, the filenames hosts.allow, hosts.equiv, and hosts.lpd match on this particular system. The meta-character may be used in any position of the pattern, as the following example illustrates:
$ cd /etc $ ls -l *lpd -rw-r--r-- 1 root wheel 103 Dec 20 1999 hosts.lpd $
This example matches any filename that is prefixed by zero or more characters and ends in the string lpd.
Unlike the *, the ? meta-character matches only one character. If there is no character in that position, there is no match. The following example shows how the ? meta-character can be used multiple times to effect a particular pattern match:
$ ls -l /etc/hosts.????? -rw-r--r-- 1 root wheel 2278 Dec 20 1999 /etc/hosts.allow -rw-r--r-- 1 root wheel 115 Dec 20 1999 /etc/hosts.equiv $
In this example, only the filenames host.allow and hosts.equiv match. The filename hosts.lpd does not match because the last two ?? in the pattern did not have characters to match with.
The [ and ] meta-characters work together to specify a class of characters. The following example lists any file that has the letter x, y, or z within it:
$ ls -d *[xyz]*
exports newsyslog.conf skeykeys ttys
gettytab security syslog.conf
$
The * meta-characters to the left and right of [xyz] permit zero or more characters to exist to the left and right of the middle pattern. However, the middle pattern [xyz] insists that a letter x, y, or z exist. In this case, there weren't any filenames with the letter z in them.
You can specify ranges of characters, as is shown in the following example:
$ ls -d *[x-z]*
exports newsyslog.conf skeykeys ttys
gettytab security syslog.conf
$
The pattern [x-z] is equivalent to specifying the letters individually as [xyz]. Multiple ranges can also be specified: [x-za-c] allows any of the characters a, b, c, x, y, and z.
If you specify an unmatched pair of [ and ] characters, the character is taken literally, as the following example demonstrates:
$ >']' $ ls -l ] -rw-r----- 1 ehg wheel 0 Jun 26 14:59 ] $
The first command creates a file named ] by using quotes. Then the file is listed using ls(1). This same behavior also exists for the closing square bracket:
$ >'[' $ ls -l [ -rw-r----- 1 ehg wheel 0 Jun 26 14:59 [ $
The next example shows how [ and ] can be used in reverse order to cause them to be interpreted as they appear.
$ ls -l ] [
-rw-r----- 1 ehg wheel 0 Jun 26 14:59 [
-rw-r----- 1 ehg wheel 0 Jun 26 14:59 ]
$
The ! meta-character has special meaning only within the [ and ] meta-character pair, and only if it occurs as the first character within a range. It is known as the "not"character in this context. For example, compare the difference between the first ls(1) command and the second:
$ cd /tmp $ ls *[0-9] psql.edit.1001.13867 tmp-I53052 tmp-d53036 tmp-s52935 tmp-D52798 tmp-M53211 tmp-f53114 win98 tmp-G52945 tmp-d52925 tmp-o53048 $ ls *[!0-9] c.t dummy.file $
The first ls(1) command lists only files and directories that end in a numeric digit (range [0-9]). The second ls(1) command, however, lists only those that do not end in a numeric digit (range [!0-9]).
In any other position within the range or outside of it, the ! character represents itself and is not special. The following example confirms this:
$ >'!' $ ls -l ! -rw-r----- 1 ehg wheel 0 Jun 26 15:10 ! $
There are times where meta-characters get in the way. To disable special treatment of meta-characters, you can escape them with the backslash character:
$ >'***FILE***' $ ls ***FILE*** tmp-D52798 tmp-d52925 tmp-s52935 c.t tmp-G52945 tmp-d53036 win98 dummy.file tmp-I53052 tmp-f53114 psql.edit.1001.13867 tmp-M53211 tmp-o53048 $ ls -l ***FILE*** -rw-r----- 1 ehg wheel 0 Jun 26 15:14 ***FILE*** $
The above example shows how a file with the unusual name of ***FILE*** was created. Then the ls(1) command is invoked to confirm its existence. Then another ls(1) command shows how the backslashes can be used to remove the special meaning from the * meta-character.
52.15.129.90