rm command in Linux: how to delete files and directories

rm command in Linux: how to delete files and directories

rm deletes files and directories on Linux, and it does it permanently.

Let me walk you through all the options available for safe deletion, with a terminal example for each one.

What rm removes when you run it

A file name is a directory entry, and that entry points at an inode which holds the metadata and the addresses of the data blocks.

rm removes the entry and drops the inode link count by one. The data stays readable while a second name points at the same inode, and the kernel releases the blocks when that count reaches zero.

The mechanism shows up in the terminal, so I created a hard link, removed the first name, and read the file back through the second one.

Terminal showing rm removing one of two names for the same file
The second name still reads the same data after the first one is removed

The command reported the one name it removed and said nothing else. Reading backup.txt still returned the line I had written into report.txt, which is the link count behaving as documented.

An open file handle behaves the same way, and a process that holds the file open keeps reading and writing after rm returns. The kernel releases that space when the process closes it.

Nothing in this path moves the file anywhere you can restore it from, because rm is the unlink call. The command returns with nothing to show you and nothing to undo.

Before you delete anything

The filesystem checks two permissions before a name disappears, write access to the file and write access to the directory.

The second one catches people out, because unlink only needs write permission on the directory. A read-only file sitting inside a directory you own is removable.

I tested that with a chmod 444 file. A read-only file inside a directory I owned came out with rm and no prompt at all, which says the prompt is not a permission check. The permission bits themselves are covered in the chmod command guide.

When standard input is a terminal, the file is unwritable, and force is absent, rm asks about that file. The same command inside a script stays silent because nothing is attached to ask.

OptionWhat it changes
-f, –forceremoves without prompting and ignores names that do not exist
-iprompts before every file
-Ione prompt when more than three names arrive or the removal is recursive
–interactive=WHENnever, once, or always
-r, -R, –recursiveremoves directories and their contents
-d, –dirremoves empty directories
-v, –verboseprints each name as it is removed
–one-file-systemskips directories on a different filesystem
–preserve-rootrefuses to recurse into /, on by default
–no-preserve-rootallows that removal

Running rm –version prints either GNU coreutils or the Rust rewrite that Ubuntu 26.10 ships as its default rm, and both aim at the same option set. Check which one answers before you lean on the guards in the table.

Read the path back before the command, not after. That step is the answer the Server Fault thread on accidental rm -rf reaches for, and it costs one second.

Removing files with rm

Which option you need depends on what you are unsure about, the names the command will receive or your own typing.

How much do you want to be askedOptionWhat happens
nothingrm filethe file goes as soon as the command returns
once, for a large or recursive command-Ione question covers the whole argument list
before every file-ieach name gets its own question
nothing, even for a protected file-fno question, and a missing name stops being an error

Removing one file or several

rm notes.txt
rm notes.txt draft.txt

Names are separated by spaces, and the command reports nothing at all when it succeeds.

Terminal showing rm -v removing notes.txt and draft.txt
rm -v reports both files it removed

Verbose output turns that silence into a receipt, which is the version I use whenever a directory holds something I might want back.

Reading the glob before the shell expands it

rm -v *.pdf

The shell expands the asterisk into a list of names before rm starts, so the command never sees the wildcard itself.

Terminal showing rm -v removing two PDF files through a shell glob
The shell expands *.pdf before rm runs

Print the expansion first when the directory matters, since echo *.pdf shows the argument list that the command will receive. Reading the directory with ls is the same check by eye.

Asking before each file

rm -i *.pdf
Terminal showing rm -i asking about each PDF file
With -i rm asks about every file and skips the ones answered with n

An answer that is not affirmative skips that file and leaves the rest of the command alone, so a partial answer is a partial delete rather than a failure. An alias can also add -i to every rm you type, and the alias guide shows where to check for one.

Answers can be piped into the prompt because it reads standard input, so a scripted yes and no deletes one file and keeps the next.

Asking once instead

rm -I *.log
Terminal showing rm -I asking one question for four files
With -I a single question covers the whole argument list

GNU rm raises that single question in two cases, with more than three file arguments or with a recursive removal. A short list passes straight through, and the name after that brings the question back.

Removing a write-protected file

Terminal showing rm asking for confirmation before removing a write-protected file
The write-protected prompt appears only when rm has a terminal on stdin

Force answers the question in advance and also drops the error for a name that does not exist, which is why it appears in cleanup scripts.

rm -f important.pdf

Names that start with a dash

A leading dash makes rm read the name as an option of its own, and the double dash ends option parsing for the rest of the line.

rm -- -notes.txt

Removing directories with rm

Which option to reach for depends on whether the directory is empty and on whether something is mounted inside it.

Empty directories

rm -dv empty1 empty2

That removes empty directories and refuses anything with contents, which is the same boundary rmdir draws. The directory removal guide covers the other routes to the same result, and find and delete empty directories clears a tree of them in one pass.

Recursive removal

rm -rv project
Terminal showing rm -rv removing a project directory from the files inside out
A recursive removal reports each file and each directory as it goes

Entries are reported as the walk returns, so the files appear before the directory that held them. Recursion is also where a wrong path hurts, since the walk follows everything under the directory you named.

Keeping the walk on one filesystem

rm -rf --one-file-system data
Terminal showing rm skipping a mount point during a recursive removal
The one-file-system option keeps the walk inside the starting filesystem

I mounted a tmpfs inside the data directory and ran that command against it, which left the mount untouched and the exit status at 1. The output named the directory rm skipped.

Without the option the same walk reaches into the mount, and the kernel answers with Device or resource busy while something holds it open.

When rm stops or fails

These are the failures that stop a delete partway.

MessageCauseWhat to run
Permission deniedyour user cannot write to the directory that holds the namecheck the directory with ls -l, then fix ownership or run the command with sudo
Directory not empty-d was used on a directory that still holds somethingrm -r for the directory and its contents
Argument list too longthe shell expanded a glob past the kernel argument limitfind with -delete, or split the list through xargs
it is dangerous to operate recursively on ‘/’the preserve-root failsafe firedconfirm the path, then decide whether the root removal is what you meant
Read-only file systemthe filesystem is mounted read-onlyremount it read-write or edit the mount options
Operation not permittedthe file carries the immutable attributeconfirm with lsattr, then clear it with chattr -i

The root failsafe is the oldest of the five, and it fires before rm opens anything. GNU rm refuses to recurse into the root directory unless –no-preserve-root is passed, which is why the command from the old danger lists no longer behaves the way those write-ups describe.

Terminal showing rm refusing to remove the root directory
The preserve-root failsafe stops the recursive removal of / before it starts
Terminal showing rm -d failing on a directory that still holds a file
rm -d removes empty directories only

A directory with contents is a boundary rather than a fault, and the message says which boundary you hit.

The argument list is the failure that surprises anyone working in a directory with a large number of files. The shell builds one argument vector, and the kernel rejects that vector once it passes the ARG_MAX limit, which is derived from the stack limit of the process.

Terminal showing the argument list too long error from a shell glob
An expanded glob can exceed the kernel argument limit

I reproduced it with 30,000 empty files and a lowered stack limit, the setting the kernel reads when it computes the limit. The same directory empties through find, which walks the tree instead of handing every name to one process, and the find command guide covers the walk itself.

find cache -name '*.tmp' -print -delete
Terminal showing find deleting tmp files and printing each path
find prints each path as it unlinks it, which the shell glob cannot do

Permission denied and a read-only filesystem both come from the kernel rather than from rm, so the repair is ownership or the mount, not another flag. The permission denied walkthrough takes the ownership route from the error message.

Recovering a file rm already removed

What you can get back depends on what happened to the inode, so check before you reach for a recovery tool.

  1. Check whether a process still holds the file open, since the kernel keeps the data alive for as long as it does.
  2. Copy the file out of /proc/<pid>/fd/ while that handle exists, which is the one route that needs no recovery tool at all.
  3. Stop writing to that filesystem, because every new write can claim the blocks the deleted file used.
  4. Restore from the newest backup or snapshot before reaching for an undelete utility.
  5. Work on an image of the filesystem when the data matters enough to spend the time.

The GNU manual says plainly that the contents of a removed file are usually recoverable, and that shred exists for the cases where they must not be. A guide on this site walks the longer version of that story, after a system directory went missing and a rebuild turned out to be faster than any recovery.

Send it to the trash instead

A delete that can be undone only needs the directory entry moved, and trash-cli does that from the terminal.

trash-put report.pdf
trash-list
trash-restore
Terminal showing trash-list listing a file moved to the trash
trash-list prints the original path of every file in the trash

The file leaves the working directory and the trash keeps the path it came from, so putting it back is one command rather than a filesystem recovery job.

Desktop sessions already ship gio trash, which moves the entry into the same trash directory the file manager uses. The extra step costs one command and it turns a wrong glob into a single trash-restore.

Frequently asked questions

Does rm delete the data or just the name?

rm removes the directory entry and drops the inode link count. The data stays readable while a second name points at that inode or a process holds the file open, and the kernel releases the blocks when the count reaches zero.

Why does rm ask for confirmation on one machine and not another?

It asks when standard input is a terminal, the file is unwritable, and force is absent. A script or a pipe has no terminal on standard input, so the same file is removed without a question.

How do I delete a directory that is not empty?

Use rm -r for the directory and its contents. When the argument list is too long for one command, find with -delete walks the tree instead.

Can I recover a file deleted with rm?

Often, when the blocks have not been reused. Check whether a process still holds the file open, stop writing to that filesystem, and try a backup or snapshot before any recovery tool.

Is rm -rf / still dangerous?

GNU rm refuses to recurse into the root directory unless –no-preserve-root is given. The command in the old warnings is the expanded form rm -rf /*, and the failsafe protects the exact root path rather than a mistyped variable.