Working with Files and Folders
Table of Contents
- Creating Folders:
mkdir - Creating Files:
touch - Copying:
cp - Moving and Renaming:
mv - Deleting:
rmandrmdir - Wildcards: Working with Many Files at Once
- Names with Spaces and Strange Characters
- Try It Yourself
Everything in this chapter happens inside your practice folder. Before you start, go there:
cd ~/cli-practice
If it doesn't exist yet, go back to the end of Moving Around and create it first.
1. Creating Folders: mkdir
You've already used mkdir (make directory) to create folders. Give
it one or more names:
mkdir drafts
mkdir music videos
What if you want a folder several levels deep, like
projects/website/src, and website doesn't exist yet?
mkdir projects/website/src
mkdir: projects/website: No such file or directory
(The exact wording of error messages differs a little between macOS and Linux, but the meaning is the same.)
mkdir refuses to create the missing folders in between. The -p
option (parents) tells it to create every missing folder along the
way:
mkdir -p projects/website/src
-p also doesn't complain if the folder already exists, which makes it
safe to use in scripts.
There's one more trick worth knowing. Brace expansion lets you write several names in one go — the shell expands the braces before running the command:
mkdir -p projects/website/{src,tests,docs}
That's the same as typing three separate paths: projects/website/src,
projects/website/tests, and projects/website/docs. Note there are
no spaces inside the braces.
2. Creating Files: touch
touch creates an empty file:
touch notes/todo.txt
touch notes/ideas.txt notes/shopping.txt
Check that they're there, and that they really are empty (size 0):
ls -l notes
-rw-r--r-- 1 dara staff 0 Oct 1 10:02 ideas.txt
-rw-r--r-- 1 dara staff 0 Oct 1 10:02 shopping.txt
-rw-r--r-- 1 dara staff 0 Oct 1 10:02 todo.txt
If the file already exists, touch doesn't change its contents — it
only updates the "last modified" time. That's where the name comes from:
it "touches" the file.
Empty files aren't much fun, so here's a quick way to put a line of text
into one. Don't worry about the > yet — chapter 6 explains it fully:
echo "Buy rice" > notes/shopping.txt
echo "Learn the command line" > notes/todo.txt
To open a file in a graphical editor instead, code notes/todo.txt
opens it in VS Code (if you have it installed), and open /
xdg-open / explorer.exe from the last chapter work on files too.
3. Copying: cp
cp (copy) takes a source and a destination:
cp notes/todo.txt notes/todo-backup.txt
That copies todo.txt to a new file called todo-backup.txt in the
same folder. If the destination is a folder, the copy goes inside
it and keeps its name:
cp notes/todo.txt drafts/
Now there's a drafts/todo.txt. The trailing / on drafts/ is
optional, but it's a good habit: it makes it obvious that you mean a
folder.
You can copy several files into a folder at once — the folder always comes last:
cp notes/ideas.txt notes/shopping.txt drafts/
Copying folders
Try copying a whole folder:
cp notes notes-copy
cp: notes is a directory (not copied).
Copying a folder means copying everything inside it, and everything
inside those folders, and so on. You have to ask for that explicitly
with -r (recursive):
cp -r notes notes-copy
Warning: if the destination file already exists,
cpoverwrites it without asking. Add-i(interactive) to make it ask first:cp -i notes/todo.txt drafts/.
4. Moving and Renaming: mv
mv (move) works just like cp, except the original is gone
afterwards. Move a file into a folder:
mv notes-copy/todo.txt projects/
Interestingly, there's no separate "rename" command. Renaming is just moving a file to a new name in the same folder:
mv drafts/todo.txt drafts/old-todo.txt
And unlike cp, mv works on folders without needing -r, because
the files inside don't need to be copied — the folder just gets a new
name or location:
mv notes-copy archive
Warning: like
cp,mvsilently overwrites a file with the same name at the destination.mv -iasks first.
5. Deleting: rm and rmdir
This is the one part of the command line that deserves real respect.
rm (remove) deletes files:
rm notes/todo-backup.txt
No question, no confirmation, and — the important part — no trash.
Files deleted with rm don't go to the Trash or Recycle Bin. There is
no "undo" and no "restore". As you saw in
Files and File Systems,
the data might technically still be on the disk for a while, but for
all practical purposes, it's gone.
rmdir removes a folder, but only if it's empty — which makes it a
safe choice:
mkdir empty-folder
rmdir empty-folder
To delete a folder and everything inside it, use rm -r:
rm -r archive
You'll often see rm -rf in tutorials. The -f (force) means
"don't ask, don't complain, even if files are write-protected or don't
exist". It's useful in scripts, and it's dangerous in your hands until
you're confident — one wrong path and a whole folder of work disappears
in a fraction of a second.
Habits that keep you safe:
- Run
pwdbefore deleting, so you know where you are. - Run
lswith the exact same path first. Ifls drafts/*.txtshows the files you expect, thenrm drafts/*.txtwill delete those files and nothing else. - Use
rm -iwhen you're unsure. It asksremove drafts/old-todo.txt?for each file; typeyto confirm. - Use
Tabto complete paths instead of typing them, so a typo can't pointrmsomewhere else. - Never run a
rm -rfcommand copied from the internet without understanding exactly what path it deletes.
6. Wildcards: Working with Many Files at Once
Typing every file name gets tedious fast. Wildcards (also called glob patterns) let you describe a group of names:
| Pattern | Matches |
|---|---|
* | Any number of any characters (including none) |
? | Exactly one character |
[abc] | One character: a, b, or c |
Let's make some files to try them on:
touch photos/beach.jpg photos/temple.jpg photos/family.png photos/scan1.pdf photos/scan2.pdf
Now:
ls photos/*.jpg # beach.jpg temple.jpg
ls photos/scan?.pdf # scan1.pdf scan2.pdf
ls photos/* # everything in photos
cp photos/*.jpg drafts/
Here's the key thing to understand: the shell expands the wildcard,
not the command. Before ls even starts, the shell looks at the
folder, finds the matching names, and replaces photos/*.jpg with
photos/beach.jpg photos/temple.jpg. ls just receives two ordinary
arguments. That's why wildcards work the same with every command —
ls, cp, mv, rm — they never even see the *.
You can test what a pattern will match, safely, using echo:
echo photos/*.pdf
photos/scan1.pdf photos/scan2.pdf
If nothing matches, zsh stops with an error (no matches found), while
Bash passes the pattern along unchanged, so the command complains it
can't find a file literally called *.gif. Either way, nothing
happens.
Two more things to know:
*doesn't match hidden files (names starting with.), sorm *won't delete.envor.git. That's a deliberate safety feature.rm *deletes every visible file in the current folder. This is exactly where the "runlsfirst" habit pays for itself.
7. Names with Spaces and Strange Characters
As you saw in chapter 2, the shell splits arguments on spaces. So this
creates two files, My and Notes.txt:
touch My Notes.txt
There are two ways to keep a name with spaces together.
Quotes around the whole name:
touch "My Notes.txt"
cp "My Notes.txt" drafts/
A backslash before each space, which tells the shell "this space is part of the name":
ls My\ Notes.txt
You don't need to remember which one to use — press Tab and the shell
will add the backslashes for you.
The same goes for other characters the shell treats specially, like
*, ?, &, $, !, (, ) and '. If a file name contains one,
quote it. Single quotes ('...') are the strictest: the shell leaves
everything inside them exactly as written.
The simplest solution of all is to avoid the problem in your own files.
Developers usually name files and folders in lowercase with hyphens:
my-notes.txt, project-plan.md, family-photos. No spaces, no
capitals, no special characters, and nothing to quote — and it's what
you'll see in almost every code project.
8. Try It Yourself
Do all of this inside ~/cli-practice.
- In a single command, create the folders
music/khmer,music/pop, andmusic/classicalusingmkdir -pand brace expansion. - Create three empty files inside
music/pop:song1.mp3,song2.mp3, andcover.jpg. - Copy only the
.mp3files intomusic/khmer. Useechoto check the pattern first. - Rename
music/pop/cover.jpgtomusic/pop/album-cover.jpg. - Move the whole
music/classicalfolder intodrafts, then check withls drafts. - Create a file called
"Final Report.txt"(with the space), then rename it tofinal-report.txt. - Delete everything inside
music/khmerwith a wildcard — but runlswith the same pattern first. Then remove the empty folder withrmdir.
You can now organize files entirely from the keyboard. Next, let's look inside those files: reading, scrolling, and editing them in the terminal.
Buy Me a Coffee
Found this tutorial helpful? Consider buying me a coffee to support more free content!