Filenames and quoting
The shell splits whatever you type into words, using spaces as the separator. That is how it knows that in cp reads.fastq backup/ there is a command and two arguments. It is also the source of one of the most common beginner frustrations.
Suppose someone hands you a file called sample 1.fastq, with a space in the name. Try to look at it:
$ cat sample 1.fastq cat: sample: No such file or directory cat: 1.fastq: No such file or directory
The shell split the name in half and handed cat two arguments instead of one. cat did what it was told. To keep the name in one piece, put quotes around it:
$ cat "sample 1.fastq"
Or escape the space with a backslash, which means "treat the next character literally":
$ cat sample\ 1.fastq
Both work. Quotes are easier to read, so prefer them.
Spaces are not the only characters with a meaning of their own. The shell also treats *, ?, $, &, |, >, ( and ) specially. You will meet each of them properly over the next few lessons, but the rule is the same for all of them: if a filename contains one, it needs quoting.
Single quotes and double quotes are not the same. Inside double quotes, the shell still expands things that start with a $. Inside single quotes, nothing is expanded at all:
$ echo "my home is $HOME" my home is /home/pete $ echo 'my home is $HOME' my home is $HOME
The rule of thumb: use double quotes when you want a variable filled in, and single quotes when you want the text exactly as written.
Tab completion, from lesson 2, is your friend here. If you start typing sam and press Tab, the shell fills in the rest and escapes any awkward characters correctly, so you do not have to think about it.
The best fix, though, is to avoid the problem when you are the one naming things. Stick to letters, digits, dots, dashes and underscores:
avoid: my reads (copy).fastq prefer: my_reads_copy.fastq
One last trap. A leading dash makes a filename look like an option:
$ rm -file rm: invalid option -- 'l'
Quoting does not help, because the problem is not word splitting, it is that rm reads it as flags. Point at the file with a path instead:
$ rm ./-file
Exercise
- Create a file whose name contains a space, using touch and quotes.
- Look at it with cat, first without quotes to see the error, then with quotes.
- Compare the output of echo "$HOME" and echo '$HOME'.
Quiz Question
Which quotes stop the shell from expanding a variable like $HOME?
Show answer
single quotes