Guides

How to delete files and directories in Linux: the rm command, rm -r and rmdir

How to delete a file in Linux with rm, remove a directory and its contents with rm -r, use rmdir and find -delete safely, and fix rm errors.

Published ~8 min read
On this page

Short answer: to delete a file in Linux, run rm file.txt. To remove a directory and all its contents, run rm -r dirname; rmdir dirname removes only an empty one. There is no recycle bin: nothing in the shell can undo rm, so list what you are about to delete first.

any Linux
rm old.log                 # delete a file
rm -r project/             # delete a directory and everything in it
rm -rf build/              # the same, without any prompt
rmdir empty-folder/        # delete a directory only if it is empty

The outputs on this page come from Debian 12 with GNU coreutils 9.1, findutils 4.9.0, bash 5.2.15 and lsof 4.95, run in a scratch directory on 21 October 2026, partly as an unprivileged user. The --preserve-root, chattr, mount point and trash-cli parts follow the coreutils, e2fsprogs and trash-cli documentation and were not run on this host. Ubuntu, Rocky Linux and AlmaLinux ship the same GNU rm.

rm cheat sheet

TaskCommand
Delete a filerm file.txt
Delete several filesrm a.log b.log c.log
Delete by patternrm *.tmp
Delete a directory and its contentsrm -r dirname
Same, never prompt, no error if missingrm -rf dirname
Delete an empty directoryrmdir dirname
Delete empty directories up a pathrmdir -p a/b/c
Confirm every filerm -i *.conf
Confirm once for a big deleterm -I *.log
Show each deletionrm -rv dirname
File whose name starts with a dashrm -- -file
File with spaces in its namerm "my file.txt"
Files older than 14 daysfind /path -name '*.log' -mtime +14 -delete
Empty a directory, hidden files includedfind dir -mindepth 1 -delete

How do I delete a file in Linux?

rm takes one or more file names and removes them without asking and without a message. -v prints each one. A name that does not exist is an error, unless you add -f, which also makes that case succeed quietly:

Example output
$ rm -v old.log
removed 'old.log'
$ rm nofile
rm: cannot remove 'nofile': No such file or directory
$ rm -f nofile; echo $?
0

Deleting a file needs write permission on the directory it is in, not on the file. A write-protected file in your own directory can be deleted, but rm asks first when it runs in a terminal:

Example output
rm: remove write-protected regular empty file 'wp'? n

Root is never asked this, and -f skips the question for everyone. Quote names with spaces: rm my file.txt tries to delete my and file.txt and fails twice with No such file or directory, while rm "my file.txt" removes the one file.

How do I remove a directory and its contents?

Plain rm refuses a directory. -r (recursive) deletes the directory, every file and every subdirectory in it:

Example output
$ rm project
rm: cannot remove 'project': Is a directory
$ rm -rv project
removed 'project/src/main.c'
removed directory 'project/src'
removed directory 'project'

rm -rf adds -f: no prompts for write-protected files, no error for names that do not exist. That makes it the usual form in scripts, and the dangerous one at a prompt, because a typo in the path is executed just as quietly. For an empty directory, rmdir is the safer tool, since it refuses anything with content:

Example output
$ rmdir d
rmdir: failed to remove 'd': Directory not empty
$ rmdir -pv d/e
rmdir: removing directory, 'd/e'
rmdir: removing directory, 'd'
rm -rrmdirrm -d
Removes contentsYes, everything belowNoNo
Directory must be emptyNoYesYes
Removes parents tooNoWith -p, while they become emptyNo
Good forDeleting a treeCleaning up after a script; a safe check that nothing is leftrm with an empty directory

rmdir -p d/e removed d/e and then d, because d was empty once e was gone; it stops at the first parent that still has content.

Prompts: -i, -I and -f

Example output
$ rm -i a
rm: remove regular empty file 'a'? n
$ rm -I c1 c2 c3 c4
rm: remove 4 arguments? n
$ rm -rI tree
rm: remove 1 argument recursively? n

-i asks for every file, which is fine for three files and useless for three thousand. -I asks once, and only when you delete more than three files or delete recursively; with three names or fewer it just runs. That makes alias rm='rm -I' in ~/.bashrc a reasonable safety net that does not get in the way. The last of -i, -I and -f on the command line wins: rm -f -i asked, rm -i -f did not, so rm -rf typed under that alias still runs without a prompt. Scripts never see the alias at all: bash does not expand aliases in a non-interactive shell.

Names with dashes, and the rm * trap

A file whose name starts with a dash looks like an option. GNU rm even tells you how to get rid of it:

Example output
$ rm -foo
rm: invalid option -- 'o'
Try 'rm ./-foo' to remove the file '-foo'.
Try 'rm --help' for more information.
$ rm -- -foo

-- ends the options, so everything after it is a file name; ./-foo works too. The same mechanism makes a bare rm * risky. The shell expands * before rm runs, and GNU rm reads a file named -r as an option wherever it lands in the list:

Example output
$ ls
-r  a  sub
$ echo rm *
rm -r a sub
$ rm *          # deletes sub/ and everything in it, without -r typed by you

Write rm ./* or rm -- * and the odd file is just a file again. Two more surprises with globs: * does not match hidden files, so rm -rf cache/* left cache/.hidden in place, and with no match at all bash passes the pattern literally, which ends in cannot remove '*.tmp': No such file or directory. To empty a directory completely but keep it, use find cache -mindepth 1 -delete.

rm -rf / and --preserve-root

GNU rm refuses to work recursively on / itself. Per the coreutils manual, --preserve-root is the default, and rm -rf / stops with it is dangerous to operate recursively on '/' unless you add --no-preserve-root. Do not rely on it:

  • rm -rf /* is not protected. The shell expands it to /bin /boot /etc ..., and none of those is /.
  • An empty variable becomes a path. rm -rf "$DIR"/* with DIR unset is rm -rf /*. Write rm -rf "${DIR:?}"/*: bash then stops with DIR: parameter null or not set before rm runs.
  • A wrong directory is just as final. rm -rf /var/www instead of /var/www/old is not protected by anything.

--preserve-root=all goes one step further: rm then also refuses any argument that sits on a different filesystem from its parent directory, such as a mounted backup disk.

Delete by age or pattern: find -delete

For anything more selective than a glob, let find pick the files, and run it with -print before you swap in -delete:

Example output
$ find logs -name '*.log' -mtime +14 -print
logs/a.log
logs/old/b.log
$ find logs -name '*.log' -mtime +14 -delete
$ find logs -type d -empty -delete          # then the folders that are now empty

Habits that prevent the bad day

  1. 1List what the command will hit

    Run the same path with ls -d or the find with -print, or put echo in front of the rm. Read the list, then press the up arrow and change only the command.

  2. 2Use absolute paths in scripts

    A relative path deletes in whatever directory the script happens to run in. Cron jobs start in the user’s home directory, not where the script lives.

  3. 3Guard variables

    "${VAR:?}" on every variable that forms a path for rm, plus set -u at the top of the script.

  4. 4Move to a trash instead, where it fits

    The trash-cli package (Debian and Ubuntu: apt install trash-cli) adds trash-put, trash-list, trash-restore and trash-empty, which use the same trash folder as desktop file managers. Handy at an interactive prompt; on a server the space is only freed once you empty the trash.

Can I undo rm?

No. rm removes the name from the directory and the filesystem marks the blocks as free; there is no trash and no undo. Recovery tools for ext4 can sometimes find blocks that nothing has overwritten yet, but a server that keeps writing logs and caches makes those odds worse by the minute. What does work:

  • A backup or a snapshot from before. On a VMHeaven VPS, snapshots are taken in the panel, by hand or on a daily, weekly or monthly schedule, and restored from there. One right before a cleanup costs a minute.
  • A process that still has the file open. Until it closes the file, the data is still on disk and readable through /proc. In the test, a deleted file held open by a process came back in full with cp /proc/PID/fd/3 data.db.recovered. sudo lsof +L1 shows the PID and the descriptor number.

rm errors and what they mean

Message ends withMeaningFix
Is a directoryrm without -r on a directoryrm -r
Directory not emptyrmdir or rm -d on a directory with content; with rm -rf, something kept writing into itrm -r, or stop the writer first
No such file or directoryTypo, unquoted spaces, or a glob that matched nothingCheck with ls; quote the name
Permission deniedNo write permission on the directory that holds the fileSee below
Operation not permittedImmutable or append-only attribute, or the sticky bit (/tmp)lsattr, then chattr -i (or -a); in /tmp, only the file owner or root deletes
Device or resource busyThe path is a mount point, or has one below itfindmnt, then umount
Read-only file systemThe filesystem is mounted read-onlyRead-only file system
invalid optionThe file name starts with a dashrm -- -name

rm: cannot remove: Permission denied

Example output (as an unprivileged user)
rm: cannot remove 'f': Permission denied
rm: cannot remove 'locked/f': Permission denied

Both files were writable by nobody but root, yet that was not the reason: the directories holding them belonged to root, and removing a name changes the directory. Inside a directory with the sticky bit, like /tmp, you may only remove your own files even with write permission on the directory; that case reports Operation not permitted instead. Check the parent with ls -ld and fix ownership or mode as described in the chmod guide, or run the rm with sudo if the files really belong to the system.

rm: cannot remove: Operation not permitted, even as root

When root gets Operation not permitted, the file usually carries the immutable attribute. Per the chattr man page, a file with +i cannot be deleted, renamed, linked or written to, by anyone, until the attribute is removed:

any Linux (ext4, XFS)
lsattr suspicious.conf          # an 'i' in the flags means immutable
sudo chattr -i suspicious.conf
sudo rm suspicious.conf

An immutable file you did not set yourself is worth a second look before you delete it: attackers use chattr +i to keep a planted cron entry or SSH key in place.

rm: cannot remove: Device or resource busy

A mounted filesystem cannot be removed from under the mount. That hits rm -r on a directory that has a mount below it, such as a Docker volume or a bind mount. findmnt -R /path lists what is mounted there. Note what happened before the error: rm descends into mounted filesystems by default and deletes what it can inside them before it fails on the mount point. Unmount first, or add --one-file-system, which makes rm skip every directory on a different filesystem from the path you gave it. On NFS, the same message can come from .nfsXXXX files, which stand in for deleted files that a process still has open; they disappear when the process closes them.

Deleted a big file, but the disk is still full?

Deleting removes the name. If a process still has the file open, typically a log file the application keeps writing, the space stays in use until the process closes it. df says full, du finds nothing. lsof +L1 lists files that have no name left:

Example output · lsof +L1 for one test process (path shortened)
COMMAND    PID USER   FD   TYPE DEVICE SIZE/OFF NLINK    NODE NAME
sleep   353107 root    3w   REG    8,1  5242880     0 3542659 /srv/app/app.log (deleted)

Restart or reload the process to free the space, or, for a log you no longer need, empty it through /proc with : > /proc/353107/fd/3, which took SIZE/OFF to 0 in the test while the process kept running. The lsof guide covers sorting this list on a busy server, and No space left on device walks through the rest of a full disk. Before deleting anything to make room, see what actually uses it with du and df.

Frequently asked

How do I delete a directory and everything in it in Linux?

Run rm -r dirname. It removes the directory with all files and subdirectories in it. rm -rf does the same without any prompt and without an error if the name does not exist. Check the path with ls -d first: there is no recycle bin and no undo.

What is the difference between rm -r and rmdir?

rmdir removes only empty directories and fails with Directory not empty otherwise, which makes it a safe cleanup step. rm -r removes a directory together with everything inside it. rmdir -p also removes parent directories that become empty.

Can I recover a file deleted with rm?

Not from the shell: rm has no trash and no undo, so restore it from a backup or a snapshot. One exception: while a running process still has the file open, its data can be copied back out of /proc/PID/fd/FD. sudo lsof +L1 shows the PID and the descriptor number.

Why is disk space not freed after deleting a large file?

A process still has the file open, so the kernel keeps its data until the process closes it. sudo lsof +L1 lists such deleted but open files. Restart or reload that process, or empty the file through /proc/PID/fd/FD, to get the space back.

Related articles

All guides