A program does not get exactly what you typed: Bash handles $, * and quotes before the run.
Before running a command, Bash prepares its arguments — the words the program will get. Spaces separate arguments. Bash replaces $HOME with the variable's value, the path of the home directory. It replaces a filename pattern like *.log from the lesson on files with the list of matching names, so the program receives ready-made names. Quotes change this preparation:
| As written | What the program gets |
|---|---|
$HOME |
the path of the home directory |
"$HOME" |
the same path as one argument, even with spaces |
'$HOME' |
the text $HOME as is |
*.log |
the names of the files that match |
'*.log' or "*.log" |
the text *.log as is |
printf '%s\n' helps you see the arguments: it prints each one on its own line.
See what printf receives
In ~/shell-lab, run the three printf calls below and compare which arguments the program received. Leave the files unchanged.
First, predict
How many lines will the first call, printf '%s\n' *.log, print?
Now start the exercise, run the command and compare your prediction with the output.
What does printf '%s\n' $HOME/my docs print — with no quotes?
-
Without quotes Bash substitutes the value of
$HOME.$HOMEstays text inside single quotes:'$HOME'. -
An unquoted space separates arguments: printf got two words and printed each on its own line. The path becomes one argument in quotes:
"$HOME/my docs". -
printf prints its arguments and opens no files, so it does not care whether the path exists. Try
printf '%s\n' /no/such/dir.
Without quotes Bash split the path at the space, and printf got two arguments: /home/student/my and docs.