How bash Expands a Command Line

  1. Shell statements are expanded
    • Variables, command-substitution, aliased, etc
    • globbing characters, only if they match
  2. I/O re-direction is set up
  3. Command is executed
    • Command sees the results of expansion, not the shell characters!

The process by which the shell interprets elements of the command line is extraordinarily complex. Here, however, is a relatively simple version of the overall process:

  1. The line is split into shell words, delimited by spaces, tabs, new lines, and a few other characters. If multiple words are enclosed within quotation marks, they are treated as a single word by bash.
  2. Aliases and characters that have special meaning to the shell, called metacharacters, are interpreted.
    bash metacharacters include $, ( ), { }, etc.

File globbing characters like * and ? are also expanded here, but they behave a bit differently.
A globbing character is only expanded if it matches files. Consider the following example:
[user@serverX ~]$ ls
file1.txt file2.txt
[user@serverX ~]$ echo *.txt
file1.txt file2.txt

[user@serverX ~]$ echo *.jpg
*.txt matches and is expanded but *.jpg does not match and is taken literally.

  1. The line is split into shell words again.
  2. File redirection is set up (>,>><, etc)
  3. The command is executed!

An example is the following command:
ll ~/*.{o,c} > $HOME/co-files-$(date -I)

Assuming that there were only two files in the home directory that ended in .c or. o, and that bob ran the previous command, it would expand to something like the following:

ls -l --color=tty /home/bob/hello.c /home/bob/hello.o > /home/bob/co-files-2008-01-01

It is important to understand that what actually gets executed is the post-expansion version of the command. ls never sees the bash metacharacters.

Leave a Comment

%d bloggers like this: