Guide to Unix/Explanations/Quoting and Filename Expansion
Special characters and substitution
editThe shell recognizes several special characters. The following are the special characters:
- \ (backslash)
- " (double quote)
- ' (single quote)
- # {number sign, pound sign, or hash)
- $ (dollar sign)
- ` (tick)
- ~ (tilde)
- { and } (braces or curly brackets)
- ( and ) (parentheses)
- * (asterisk, star or splat)
- ? (question mark)
- < (less than sign)
- > (greater than sign)
- & (ampersand)
- | (pipe)
- ; (semicolon)
- ! (exclamation point or bang)
They are all special characters in the Bourne shell, except for the exclamation point. However, many Bourne and non-Bourne shells also make special the exclamation point. When the shell sees special characters, it does something more complex than simply running the command that you typed.
Some special characters trigger substitution, when parts of the command are replaced with other text. One common form of substitution is filename expansion, which saves you work when typing longer filenames and lists of filenames.
To test substitution, we need the echo command. This command simply echoes its arguments (including any changes made to the arguments by the shell). All options except "-n" are ignored.
$ echo -lnQ arg1 arg2 arg3 -lnQ arg1 arg2 arg3
Quoting
editQuoting is used to preserve the literal meaning of special characters.
Here is an example of several types of quoting, which will be referred to in the rest of this section (there are many unnecessary things in this which you should find after reading this section, but are used for the sake of example):
$ echo There is \"a small possibility\" that '/etc/*tab' are " not " text and a backslash will not be printed after this. \\ There is "a small possibility" that /etc/*tab are not text and a backslash will not be printed after this. \
Backslash
editA backslash (\) simply stops the shell from thinking that certain characters are special. In the example above, it was used to print literally the doublequote character.
To print a backslash, use two backslashes in a row.
Now commands that want special shell characters for input will work.
Paired quoting characters
editPaired characters affect whatever is between them.
Single quotes
editSingle quotes prevent all expansion, thus preserving the literal meaning for all chars.
In the example, single quotes were used to prevent the * from expanding.
Single quotes can't be used within single quotes. Any 2nd single quote always terminates the 1st, whereas a 3rd single quote begins the next pair.
Double quotes
editDouble quotes are like single quotes, but don't preserve the literal meaning of $, \ when followed by a dollar sign, tick, double quote, or backslash, and `.
In the example, double quotes were used to preserve the literal meaning of spaces.
Filename expansion
editFilename expansion uses the following characters to avoid typing long lists of files:
* ? { }
* and ?
editThe shell globbing characters of * and ? are used to form patterns. The shell searches for existing files that match the patterns and does a subsitution.
- * matches 0 or more characters, except /
- ? matches any 1 character except /
When more than one file is matched, the files are separated by spaces, as separate arguments.
For example, /etc/ss* means all of the files inside the /etc directory which begin with the letters ss. The echo command demonstrates the substitution. The results may differ on your system, depending on what files you have.
$ echo /etc/ss* /etc/ssh /etc/ssl
The echo command did this because it thinks that you ran echo /etc/ssh /etc/ssl. The shell substituted those names for /etc/ss*. Though /etc/ssh/ssh_config exists on many systems, it appeared not above, because * never matches /.
Now here is something more useful. We will use substitution with a command other than "echo". We will combine filename expansion with the ls command.
$ ls /etc/ss* /etc/ssh: ssh_config ssh_host_key ssh_host_rsa_key.pub ssh_host_dsa_key ssh_host_key.pub sshd_config ssh_host_dsa_key.pub ssh_host_rsa_key /etc/ssl: lib openssl.cnf private x509v3.cnf
Notice how the * reduced extra typing. If we did ls /etc/s*, we would probably further reduce the amount the user needs to type.
Here is an example of the ? character at work:
$ ls /etc/ssh/ssh_host_???_key /etc/ssh/ssh_host_dsa_key /etc/ssh/ssh_host_rsa_key
When expansion fails
editSometimes, when using * or ?, no files are found. In this case, the shell does not give an error; it simply does no substitution. Suppose that in the machine on the example above, we make a mistake and typed /etc/sss* which matches nothing. Then the shell would do no substitution:
$ echo /etc/sss* /etc/sss*
Curly brackets expansion
editThe curly brackets help when typing several similar arguments, especially filenames. The filenames do not need to actually exist. Example:
$ echo /etc/ss{h,l,ssnakes} /etc/ssh /etc/ssl /etc/ssssnakes
They are very useful for long lists of files in the same directories:
$ echo /bin/{ls,mv,cp} /sbin/{halt,reboot} /bin/ls /bin/mv /bin/cp /sbin/halt /sbin/reboot
You can also use them to print the alphabet (or numbers):
$ echo {z..a} z y x w v u t s r q p o n m l k j i h g f e d c b a