Linux & Bash · Part I · Module 3 · Creating and Changing Files and Directories
File Names, Spaces and Characters That Need Care
A file name looks like the simplest thing in this course. It is text; you type it; the file gets it. In fact two different systems have opinions about that text, and they disagree. The filesystem will accept almost anything you give it, including spaces, punctuation and characters you cannot see. The shell, standing in between, treats about a dozen characters as instructions addressed to itself and acts on them before the command is even started. Everything awkward about file names lives in that gap — and once you can see the gap, a whole category of baffling behaviour becomes predictable.
Foundation17 min readLinuxBashPart IFundamentalsFilesQuoting
Part I · Module 3 · Chapter 3.4 · File Names, Spaces and Characters That Need Care
1. Two Systems, Two Sets of Rules
Chapter 1.1 established that the kernel and the programs around it are different layers. File names are a place where that distinction becomes immediately practical.
What the filesystem permits. A name may contain almost any character. There are exactly two exceptions:
/— reserved as the separator between path components, per Chapter 2.1.- the null character — which marks the end of a name internally and so cannot be inside one.
Everything else is allowed: spaces, tabs, quotes, asterisks, newlines, emoji. The filesystem stores the bytes you give it and does not care.
What the shell does with the characters. Chapter 1.2 established step 2 of the shell loop: before a command runs, Bash splits the line into words and acts on characters that mean something to it. A dozen or so characters are in that category.
So a name like my notes.txt is perfectly legal as a file name and simultaneously ambiguous as something to type. The filesystem is happy; the shell has already made a decision you did not intend.
2. The Space: One Name Becomes Two Files
Here is the demonstration, and it is worth running yourself:
$ mkdir demo && cd demo
$ touch my notes.txt
$ ls
my notes.txtYou asked for one file and got two.
Nothing malfunctioned. Chapter 1.5 taught that a command line is words separated by whitespace, and that the shell splits on that whitespace before the program starts. The shell saw three words — touch, my, notes.txt — and handed touch two operands. touch creates one file per operand, as Chapter 3.1 described, so it created two.
touch never saw a space. It was given two separate names, and it did its job perfectly.
The same split happens with every command, which is where it stops being a curiosity:
$ rm my notes.txtThat removes two files. If you meant the single file my notes.txt, you have just deleted two different things — and per Chapter 3.3, there is no undo. This is the single most common way the space problem causes real damage.
3. Three Ways to Write It Properly
All three of these create one file named my notes.txt:
$ touch "my notes.txt"
$ touch 'my notes.txt'
$ touch my\ notes.txt$ ls
my notes.txtOne entry. The rules, one line each:
| Form | What it does |
|---|---|
"double quotes" | the enclosed text is one word; most special characters are disabled, but some still work |
'single quotes' | the enclosed text is one word, and every character inside is literal |
backslash | the single character immediately after it is literal |
For a name with a space in it, all three work and single quotes are the simplest to reason about: everything inside is exactly what it says.
Tab completion does the quoting for you
The practical answer most of the time is not to type the name at all. Press Tab part-way through a name and Bash completes it, inserting the escaping itself:
$ ls my<Tab>
$ ls my\ notes.txtBash produced the backslash. This is worth a habit for a reason beyond convenience: a completed name is a name that exists, so completion also catches the typo you were about to make.
4. The Characters the Shell Claims
Spaces are the common case; they are not the only one. These characters mean something to Bash when they appear unquoted:
| Characters | Roughly what Bash does with them |
|---|---|
| space, tab, newline | separate the line into words — §2 |
* ? [ ] | match existing file names — Chapter 3.5, next |
~ | your home directory — Chapter 2.3 |
$ | the value of something — Module 8 |
& ; | control how and when commands run — Module 11 |
< > | send input and output elsewhere — Module 12 |
" ' \ | the quoting from §3 |
# | start of a comment, so the rest of the line is ignored |
! | history, in an interactive shell — Chapter 1.8 |
You are not expected to memorise that. The useful takeaway is the shape: if a name contains punctuation, assume the shell has an opinion about it and quote it.
Two of them cause enough trouble on their own to be worth a line each.
$ in a name. A file called cost$5.txt is legal, and unquoted the shell will try to substitute something. Quote it.
# in a name. Everything from an unquoted # to the end of the line is discarded as a comment:
$ touch report#2.txt
$ ls
reportThe shell discarded #2.txt before touch ran, so you got a file called report. No error, because nothing was wrong as far as the shell was concerned.
5. The Leading Dash
A name that begins with - is a special case, because the problem is not the shell at all.
Chapter 1.5 established that the shell passes words through and the program decides which of them are options. A word starting with a dash looks exactly like an option:
$ rm -notes.txt
rm: illegal option -- n
usage: rm [-f | -i] [-dIPRrvWx] file ...Quoting does not help here — the shell was never the problem. rm received the word and read it as options, which is its job.
The fix is the -- convention from Chapter 1.5: everything after it is an operand, whatever it looks like.
$ rm -- -notes.txtThis matters more than it seems, because such names appear by accident — a command whose output became a file name, a mis-pasted line — and the file then resists every ordinary attempt to remove it until you remember --.
A second route works too, and is worth knowing because it needs nothing new: give a path rather than a bare name, so the word no longer starts with a dash.
$ rm ./-notes.txtThat is Chapter 2.3's ./ doing a second job.
6. Case Matters — and Here Is the Exception
On Linux filesystems, names are case-sensitive. These are three different files, able to sit side by side in one directory:
$ touch Makefile makefile MAKEFILE
$ ls
MAKEFILE Makefile makefileSo ls Makefile and ls makefile are different requests, and cd RTL will not find a directory called rtl.
Now the honesty, because §38 of good technical writing requires it: this is a property of the filesystem, not of Linux as such. The commands in this course were run on a machine whose filesystem is case-insensitive by default, and there the same three commands produce one file — the second and third touch simply update the timestamp of the first.
What to take from that:
- Assume case-sensitive. Every mainstream Linux filesystem is, and that is where your work will run.
- Do not rely on case to distinguish two files.
Report.txtandreport.txtas two different documents is a decision that breaks the moment the project is copied to a machine that disagrees. - Type the case you see.
lsshows you the real name; use it exactly.
7. Characters You Cannot See
The hardest names are the ones that look ordinary.
A trailing space. report.txt and report.txt are different names, and in a listing they are indistinguishable. The symptom is a file you cannot open by the name you can plainly read.
A leading space. Sorts oddly and looks like an indentation glitch.
A carriage return at the end. The classic source: a file created on Windows, or a name copied from a document. Chapter 4.7 covers these line endings; the version that bites here is a name whose last character is invisible.
GNU ls can show them:
$ ls -b
report.txt
report.txt\-b prints non-printing characters as escape sequences, so the odd one becomes visible. It is a GNU option and not available everywhere — Chapter 1.6's rule applies, as always: check the manual on the machine you are on.
When a file "does not exist" but you can see it in a listing, this is a strong suspect. The reliable fix is to let the shell type the name for you with Tab completion, which reproduces the real name including the parts you cannot see.
8. The Real Advice: Choose Boring Names
Everything above is how to survive awkward names. The better position is not to create them.
A naming convention that never causes any of this:
- letters, digits,
.,-and_; - no spaces — use
_or-instead; - no other punctuation;
- do not start a name with
-; - lowercase by default, so case-sensitivity is never load-bearing.
run_042.log good
regression-summary good
alu_v2.sv good
my notes.txt needs quoting every single time
report#2.txt loses half its name unquoted
-output.txt fights every command
Report.TXT depends on the filesystem agreeing with youThis is not fussiness. A name you created is a name that will be typed by colleagues, pasted into messages, and eventually handled by automation — and every awkward character is a place where one of those goes wrong quietly.
9. Why This Matters in Engineering Work
Two concrete consequences, neither needing semiconductor knowledge.
Awkward names break automation long before they inconvenience a person. A space in a name is mildly annoying to type and genuinely destructive to a sequence of commands that assumes one name is one word. Module 14 introduces the tools that handle this correctly, and Module 20 makes handling it a requirement rather than a nicety. The habit of boring names is what keeps that from mattering.
Case-sensitivity catches people moving between machines. A project authored where case does not matter, then built where it does, fails on the first name whose case was written inconsistently — and the error points at a missing file that is plainly there. Knowing the two possible behaviours is what turns that into a five-minute fix.
10. Practice
Question 1. touch quarterly report.txt — how many files are created, what are they called, and which component made that decision?
Question 2. Write three different commands that each create one file named quarterly report.txt.
Question 3. You have a file named my notes.txt and you run rm my notes.txt. What happens, and why is this the most dangerous example in the chapter?
Question 4. touch draft #1.txt creates a file called draft. Explain exactly what the shell did with the rest of the line — and say why touch draft#1.txt, with no space, does not behave the same way.
Question 5. A file is named -report.txt. Explain why quoting it does not help, then give two different commands that remove it.
Question 6. You run cd RTL and get No such file or directory, but ls clearly shows rtl. What is the explanation on a typical Linux filesystem?
Question 7. ls shows results.txt, but cat results.txt reports that the file does not exist. Give the most likely cause and two ways to work out what the real name is.
Question 8. Rewrite each of these as a name that needs no quoting: final report v2.txt, data(new).csv, -temp.log.
The same reasoning decides what a cleanup script may touch: Chapter 28.1 classifies every file a flow produces by whether deleting it is reversible.
11. Remember
- The filesystem permits almost any character in a name — only
/and the null character are excluded. The shell is what makes some of them difficult. - A space splits one name into two words, so
touch my notes.txtcreates two files andrm my notes.txtremoves two files. Nothing warns you. - Three ways to write a name literally:
"double quotes",'single quotes', and a\before one character. Which expansions each one suppresses is Module 9. - Tab completion writes the escaping for you — and only completes names that actually exist.
- About a dozen characters mean something to Bash. If a name has punctuation in it, assume the shell has an opinion and quote it.
#discards the rest of the line, so an unquoted#in a name silently truncates it.- A leading dash is a program problem, not a shell problem. Quoting does not help;
--or a./prefix does. - Assume names are case-sensitive, because every mainstream Linux filesystem is — while knowing that some filesystems are not, which is where cross-machine surprises come from.
- Invisible characters are a real cause of a file that is visibly there and apparently missing. Let Tab completion type it.
- Create boring names: letters, digits, dot, dash, underscore, no spaces, no leading dash.
This chapter covered the characters that are part of a name. The next one covers the characters that are not names at all — the patterns the shell replaces with a list of real names before the command starts, and the single technique that makes them safe to use with the command from Chapter 3.3.
Where this fits
Part of the Linux & Bash curriculum.
