rm — Delete Files and Directories

Practical guide to rm: delete files and directories, prompt safely with -i/-I, remove recursively with -rf, and avoid disasters like rm -rf /.

rm (remove) deletes files and directories from the filesystem – and it does so for good: unlike moving things to a trash bin, nothing is kept around, and deleted data cannot be recovered without a backup. Day to day you reach for rm to clear out temporary files, stale logs or entire project folders. Precisely because it is irreversible, it pays to know the safe variants: rm -i asks before each file, while rm -I warns once before large or recursive deletions. Take special care with rm -rf next to variables or glob patterns – an empty $VAR or a stray /* can wipe out whole systems.

Basic Removal

rm <file> — Remove a single file.

rm temp.txt

rm <file1> <file2> <file3> — Remove multiple files at once.

rm old.log debug.log error.log

rm *.tmp — Remove all files matching a glob pattern.

rm *.tmp

rm -v <file> — Verbose mode. Print each file as it is removed.

rm -v *.log

Interactive & Safe Removal

rm -i <file> — Interactive mode. Prompt for confirmation before each file.

rm -i important-data.*

rm -I <files> — Prompt once before removing more than 3 files or when removing recursively.

rm -I *.log

rm --interactive=once <files> — Same as -I. Prompt once for bulk removals.

rm --interactive=once /tmp/session_*

rm -f <file> — Force removal. Never prompt and ignore nonexistent files.

rm -f lockfile.pid

Directory Removal

rm -r <directory> — Remove a directory and all its contents recursively.

rm -r ./old-project/

rm -rf <directory> — Force remove a directory recursively without prompts. Use with extreme caution.

rm -rf ./build/

rm -ri <directory> — Remove a directory recursively with confirmation for each file.

rm -ri ./unknown-folder/

rm -d <directory> — Remove an empty directory. Fails if the directory is not empty.

rm -d ./empty-dir/

rmdir <directory> — Remove an empty directory (dedicated command, same as rm -d).

rmdir ./empty-dir/

rmdir -p <path/to/nested/dir> — Remove a directory and its empty parent directories.

rmdir -p ./a/b/c/

Safety Options

rm --preserve-root — Refuse to operate recursively on /. This is the default behavior.

rm -rf --preserve-root /some/path/

rm --preserve-root=all — Additionally reject any argument that is a mount point.

rm -rf --preserve-root=all /mnt/data/

rm --one-file-system -r <directory> — Skip directories on different filesystems during recursive removal.

rm -rf --one-file-system /var/tmp/

Special Cases

rm -- <file> — Remove a file whose name starts with a dash. The -- signals end of options.

rm -- -strange-filename.txt

rm ./-<file> — Alternative: remove a dash-prefixed file by prepending ./

rm ./-strange-filename.txt

rm -f <file_with_special_chars> — Force remove files with special characters in the name.

rm -f 'file with spaces.txt'

find <dir> -inum <inode> -delete — Remove a file by its inode number. Last resort for unremovable filenames.

ls -i; find . -inum 1234567 -delete

Find & Remove Patterns

find <dir> -name '<pattern>' -delete — Find and delete files by name pattern. Faster than -exec rm.

find . -name '*.tmp' -delete

find <dir> -name '<pattern>' -type f -delete — Delete only files (not directories) matching a pattern.

find . -name '.DS_Store' -type f -delete

find <dir> -empty -type d -delete — Delete all empty directories within a tree.

find ./project/ -empty -type d -delete

find <dir> -mtime +<days> -delete — Delete files older than N days.

find /var/log/ -name '*.log' -mtime +90 -delete

find <dir> -size +<size> -delete — Delete files larger than a given size.

find /tmp/ -size +100M -delete

find <dir> -name '<pattern>' -print -delete — Print each file before deleting it (verification output).

find . -name '*.bak' -print -delete

find <dir> -name '<pattern>' -print0 | xargs -0 rm -v — Find and remove files safely with verbose output. Handles spaces in filenames.

find . -name '*.cache' -print0 | xargs -0 rm -v

Safer Alternatives

mv <file> /tmp/ — Move to /tmp instead of deleting. Files are cleaned on reboot.

mv suspicious-file.dat /tmp/

trash-put <file> — Move file to trash (trash-cli package). Can be recovered later.

trash-put document.pdf

trash-list — List all files in the trash (trash-cli).

trash-list

trash-restore — Interactively restore a file from the trash (trash-cli).

trash-restore

trash-empty — Permanently empty the trash (trash-cli).

trash-empty

alias rm='rm -I' — Shell alias to always prompt before bulk deletions.

alias rm='rm -I'

Dangerous Commands to Avoid

rm -rf / — NEVER RUN. Attempts to delete the entire filesystem. Blocked by --preserve-root default.

# DO NOT RUN — destroys your entire system

rm -rf /* — NEVER RUN. Bypasses --preserve-root by expanding /* to individual paths. Destroys everything.

# DO NOT RUN — the glob expansion bypasses root protection

rm -rf $VARIABLE/ — DANGEROUS if variable is empty or unset. Expands to rm -rf / which deletes everything.

# ALWAYS quote and check: rm -rf "${DIR:?Variable not set}/"

rm -rf "${DIR:?}"/* — Safe pattern. The :? causes the shell to abort with an error if DIR is empty or unset.

DIR=/var/cache/app; rm -rf "${DIR:?Variable not set}"/*

Conclusion

rm is powerful and final: there is no trash bin, and once data is gone it is gone unless you have a backup. For everyday use, rm <file>, rm -r <directory> and the find … -delete patterns cover most needs. Stay aware of the dangerous cases: rm -rf with an empty variable, a stray space before /, or a /* can erase an entire system. Two simple habits protect you – quote and guard variables with "${DIR:?}", and set an alias rm='rm -I' so the shell prompts before bulk deletions. When you need recoverability, use trash-cli instead of rm.

Further Reading

  • mv – move or rename files instead of deleting them
  • cp – copy files and directories
  • find – locate files and remove them selectively with -delete