NEXT UP previous
Next: I/O Redirection

Pathname Expansion

In all the examples of Linux commands presented in my other tutorials, any required pathnames have been specified in full. There are various ways in which the pathnames can be abbreviated and the shell will then expand them before the names are passed to any commands. Pathnames containing these abbreviation characters are called regular expressions. For example:

	$ cp text/* backup

Here the asterisk (*) is used to mean any file name (except those that start with a dot (.) character which are treated specially by most commands. This command line therefore says: copy all the visible files in the text directory into the backup directory, preserving the original names. In actual fact, the cp command need know nothing about the * character, because the expansion of this character is performed by the shell before cp even gets a look-in. This means that when the cp command is given access to the file names passed to it as command line parameters, what it sees will be a command line like:

	$ cp text/motd text/passwd backup

This is because the shell has looked into the text directory, sorted out the names of all the files in the directory, and explicitly listed them on the command line that it passes to cp. You have already seen that the cp command can cope with copying multiple files into a directory, and consequently it has no problem with executing the shell expanded command line.

Another special character used in file names that the shell will expand is the question mark (query ‘?’). This character is allowed to stand in for any single character. The following command and its output illustrates the point:

	$ ls /dev/tty?
	/dev/tty0  /dev/tty2  /dev/tty4  /dev/tty6  /dev/tty8 
	/dev/tty1  /dev/tty3  /dev/tty5  /dev/tty7  /dev/tty9

Here, the ten files tty0 through tty9, are listed as the only files in the /dev directory which match the pattern tty? (i.e. tty followed by another single character). Rather than allowing any single character, it is also possible to give an explicit list of characters, any one of which can be matched. This is done by enclosing the list in square brackets ([ ] ):

	$ ls /dev/tty?[23456]
	/dev/ttyS2	/dev/ttyp2	/dev/ttyq2	/dev/ttyr2	/dev/ttys2
	/dev/ttyS3	/dev/ttyp3	/dev/ttyq3	/dev/ttyr3	/dev/ttys3
	/dev/ttyS4	/dev/ttyp4	/dev/ttyq4	/dev/ttyr4	/dev/ttys4
	/dev/ttyS5	/dev/ttyp5	/dev/ttyq5	/dev/ttyr5	/dev/ttys5
	/dev/ttyS6	/dev/ttyp6	/dev/ttyq6	/dev/ttyr6	/dev/ttys6

Here, all files are listed which match the pattern /dev/tty followed by any single character followed by a digit in the range 2 to 6.

This range could also have been specified as a pair of characters separated by a hyphen (-), as follows:

	$ ls /dev/tty?[2-6]

A final form of expansion for pathnames allows you to specify a list of whole words from which to make a match rather than just single characters. The list of words is separated by commas and enclosed in curly brackets {}, as the following commands show:

	$ mkdir /usr/tmp/{bin, doc, lib, src}
	$ ls /usr/tmp
	bin doc  lib  src

Don't forget, that all these pathname expansions are performed by the shell itself and, therefore, the commands invoked by the shell have no need to be able to deal with these special characters. This also has implications if you ever come to write your own commands, perhaps as C programs, because they, too, will be able to take advantage of this service offered by the shell without the need to be able to perform the expansion themselves.

Sometimes, however, you may wish to use a command (or write one of your own) which can have any or all of these special characters passed to it in its parameter list. In this case you need to use a technique called quoting, which tells the shell to ignore the special meaning of the quoted characters and just to treat them as though they were ordinary characters instead.

The bash shell supports three quoting mechanisms: escape characters (\), single quotes () and double quotes (").

A backslash (\) character placed immediately before any of the shell's special characters will tell the shell to ignore its special meaning. If this escape character mechanism is used then a backslash needs to be added before each individual character whose special meaning is to be suppressed:

	$ cd
	$ mv text/motd text/m\*\?
	$ ls text
	m*?          passwd

Any string of characters enclosed in single quotes () will suppress the special meaning of all the characters contained in the string:

	$ cat 'text/m*?’
	motd contents in here.

Any string of characters enclosed in double quotes (") will suppress the special meaning of all the pathname expansion characters you have seen in this chapter:

	$ mv "text/m*?" text/motd
	$ ls text
	motd	passwd

You should note, however, that there are some other special characters you have not yet seen that bash uses, which retain their special functionality even within double quotes.


NEXT UP previous
Next: I/O Redirection