Files and directories
rm
Delete files, and with -r whole directory trees. There is no undo.
rm [OPTION...] FILE...
rm removes directory entries. On the command line there is no trash can: once the last link
to a file is gone and no process has it open, the space is reused. Treat every rm as final.
By default rm only deletes files. -r (recursive) is needed for directories and everything in
them, and -f (force) suppresses errors about missing files and stops all prompting. rm -rf
is therefore the most destructive everyday command there is: double-check the path, especially
when it contains a variable.
Interactive options are a seatbelt: -i asks before every file, -I asks once before deleting
more than three files or recursing. To remove only empty directories, rmdir is safer.
Examples
Delete a file
rm todo.txt
ls todo.txt
ls: cannot access 'todo.txt': No such file or directory
rm prints nothing when it succeeds. The ls afterwards fails because the file is gone.
Delete files matching a pattern
Setup run before this example
touch report1.bak report2.bak notes.bakrm -v *.bak
removed 'notes.bak' removed 'report1.bak' removed 'report2.bak'
The shell expands *.bak into the three names; -v makes rm report each removal. Run
ls *.bak (or echo rm *.bak) first to see exactly what a pattern matches.
Removing a file that does not exist
rm nosuch.txt
rm: cannot remove 'nosuch.txt': No such file or directory
Without -f, a missing file is an error with exit status 1.
Ignore missing files with -f
rm -f nosuch.txt
echo "exit status: $?"
exit status: 0
-f makes a missing file a non-event, which is what cleanup code in scripts wants:
rm -f "$tmpfile" succeeds whether or not the file was ever created.
rm refuses directories without -r
rm logs
rm: cannot remove 'logs': Is a directory
Directories need -r. This is deliberate: deleting a directory deletes everything below it.
Delete a directory and everything in it
rm -rv logs
removed 'logs/error.log' removed 'logs/app.log' removed 'logs/app.log.1' removed directory 'logs'
-r descends into the directory, deletes the files, then the directory itself. -v shows
the order: contents first, logs last.
Ask before each deletion
rm -i todo.txt notes.txt
ls todo.txt notes.txt
rm: remove regular file 'todo.txt'? rm: remove regular file 'notes.txt'? ls: cannot access 'todo.txt': No such file or directory notes.txt
-i asks for each file and reads the answer from standard input. Here the input answered
y for todo.txt and n for notes.txt, so only notes.txt survives. The prompts have no
trailing newline, so they run together on one line.
Delete a file whose name starts with a dash
Setup run before this example
touch -- -draft.txtrm -draft.txt
rm -- -draft.txt && echo removed
rm: invalid option -- 'a' Try 'rm ./-draft.txt' to remove the file '-draft.txt'. Try 'rm --help' for more information. removed
rm -draft.txt is parsed as a cluster of options (-d, -r, -a, ...) and fails on the
unknown -a; GNU rm even suggests the fix. -- ends option parsing, so everything after
it is a file name. rm ./-draft.txt works too.
Delete a file with spaces in its name
rm file with spaces.txt
rm "file with spaces.txt" && echo removed
rm: cannot remove 'file': No such file or directory rm: cannot remove 'with': No such file or directory rm: cannot remove 'spaces.txt': No such file or directory removed
Unquoted, the name is split into three arguments, none of which exists. Quoted, it is one.
Removing a symlink removes only the link
rm link-to-notes
ls -l notes.txt
-rw-rw-r-- 1 dev dev 190 Oct 25 05:30 notes.txt
rm deletes the link itself, never the file it points to; notes.txt is untouched.
Files you do not have write permission on
Setup run before this example
chmod a-w todo.txtrm todo.txt && echo removed
removed
What matters for deleting is write permission on the directory, not on the file. In a
terminal, rm would first ask "remove write-protected regular file?"; with no terminal on
standard input, as here, it just removes it.
Guard against an empty variable
dir=""
rm -rf "${dir:?is empty}/cache"
/bin/bash: line 2: dir: is empty
With an empty dir, rm -rf "$dir/cache" would target /cache. ${dir:?...} makes bash
print the message and abort before rm ever runs; a non-interactive bash (a script) exits
on the spot, here with status 127.
Common pitfalls
rm -rf $dir/with an unsetdirbecomesrm -rf /. Quote variables and use${dir:?}, orset -u(see Strict mode and its caveats).A stray space is fatal:
rm -rf ./build /*deletes./buildand then everything matching/*. Read the command again before pressing Enter.Deleting a large log file that a process still has open frees no space until the process closes it;
lsof+L1lists such files. Truncate it instead with: > fileortruncate-s 0.rmcannot really erase data: blocks remain on disk until overwritten.shredexists but is unreliable on SSDs and journaling or copy-on-write filesystems.
GNU vs BSD and macOS
The examples above ran the GNU/Linux version. These are the differences that matter on macOS and the BSDs (written from their documentation, not run here).
GNU
rmrefusesrm -rf /unless you add--no-preserve-root; modern BSD/macOSrmalso refuses to remove/.-I(prompt once) and--one-file-systemare GNU options; check your system's man page on BSD/macOS.
Options worth knowing
A selection, described in our own words. For the full list, see rm(1) or rm --help.
| Option | What it does |
|---|---|
-r, --recursive | Remove directories and their contents. |
-R | Same as -r. |
-f, --force | Ignore missing files and never prompt. |
-i | Prompt before every removal. |
-I | Prompt once before removing more than three files or recursing. |
-v, --verbose | Print each file as it is removed. |
-d, --dir | Also remove empty directories, like rmdir. |
--interactive[=WHEN] | Prompt never, once or always. |
--one-file-system | With -r, skip directories on other filesystems. |
--preserve-root | Refuse to operate on / (the default). |
--no-preserve-root | Allow recursive removal of /; almost never what you want. |
Related
rmdirRemove empty directories, and refuse if they are not empty.mvMove or rename files and directories.findWalk a directory tree and print, or act on, every file that matches a set of tests.lsofList open files and the processes holding them, including network sockets, deleted files and working directories.truncateShrink or extend a file to an exact size, creating it if needed.- QuotingSingle quotes, double quotes, backslashes and $'...', what each protects, and the unquoted-variable bugs they prevent, each shown failing and then fixed.
- Strict mode and its caveatsWhat set -euo pipefail actually does, the cases where -e silently does nothing, the traps in -u and pipefail, and a balanced way to use it.
- Parameter expansionThe ${...} operators for defaults, lengths, substrings, trimming prefixes and suffixes, search and replace, and case conversion, without calling sed or cut.