---
title: 'Deletion and Irreversibility'
source: 'https://academia.sh/en/courses/introduction-to-linux/deletion-and-irreversibility'
course: 'Introduction to Linux'
language: en
updated: '2026-08-17T18:09:55+00:00'
license: 'CC BY-SA 4.0'
---

# Deletion and Irreversibility

Defining deletion as unlinking, the effect of open file descriptors, verification habits for destructive commands, and the danger of filenames starting with a dash.

The previous lesson's commands could lose data too, but all of them did it by
overwriting something. Deletion destroys directly, and the file system has no
"undo" operation: a file deleted from the command line does not go to a trash can.

This lesson first defines what deletion is at the kernel level — the definition
explains why a deleted file can sometimes still be read — and then establishes the
verification habits to apply with destructive commands.

## Deleting Is Unlinking

What the `rm` command does is narrower than its name suggests: it **removes the
directory entry**. The name of this operation at the system call level is `unlink`.

Every file's metadata keeps a **link count**: the number of directory entries
pointing to the file. `rm` decreases this count by one. The data blocks are freed
only when both conditions are met:

1. The link count has dropped to zero.
2. No process is left holding the file open.

The second condition can be shown directly:

```
$ printf 'temporary data\n' > /tmp/temp.txt
$ exec 3< /tmp/temp.txt
$ rm /tmp/temp.txt
$ ls -l /tmp/temp.txt
ls: cannot access '/tmp/temp.txt': No such file or directory
$ cat <&3
temporary data
$ exec 3<&-
```

The file has been deleted: its name is not in the directory, and listing gives an
error. Yet its content could still be read, because a **file descriptor** is holding
it open. The moment the descriptor closes, the data actually becomes free.

This behavior has two practical consequences. First, when a running program's log
file is deleted, the program keeps writing and the disk space is not reclaimed; the
space is freed only when the program restarts. Second, deleting a file a program is
using does not crash it — the program uses the file by its descriptor, not by its
name.

If the link count is greater than one, deletion does not touch the data at all; only
one of the names goes. How this is possible is the subject of the next lesson.

## Deleting Directories

Directories are deleted with two commands, and the difference between them is a
safety criterion.

`rmdir` deletes only **empty** directories:

```
$ ls archive
raw-p  raw-backup
$ rmdir archive/raw-p
rmdir: failed to remove 'archive/raw-p': Directory not empty
```

`rm -r` deletes a directory together with its contents, recursively:

```
$ rm -r archive/raw-p
$ ls archive
raw-backup
```

This removes the second backup that was created in the previous lesson to
demonstrate the effect of the `-p` option; the `raw-backup` directory continues to
exist.

`rmdir` failing is not a flaw, it is a feature: when it reports that the directory
is not empty, it announces the presence of content that was not intended to be
deleted. Using `rmdir` to verify that a directory has been emptied is safer than
using `rm -r`.

## What `-f` Does and Does Not Do

`rm` gives an error for a nonexistent file and returns a non-zero status:

```
$ rm /tmp/demo2/missing.txt
rm: cannot remove '/tmp/demo2/missing.txt': No such file or directory
$ echo $?
1
$ rm -f /tmp/demo2/missing.txt
$ echo $?
0
```

The `-f` option does two things: it gives no error for nonexistent files, and it
does not ask for confirmation. It does not increase the power to delete — it does
not delete a file that cannot be deleted; permissions still apply.

`-f` is used often in scripts because the "fine if it is already gone" behavior is
needed. But because it also turns off confirmation questions, combined with `-r` it
becomes the most dangerous form.

## Verification Habits

A fact established in the shell lesson turns into a safety tool here: expansion is
done by the shell, the command only sees the result. So the result can be seen
before the command is run.

```
$ echo data/raw/*.csv
data/raw/measurement-01.csv data/raw/measurement-02.csv data/raw/measurement-03.csv
$ echo rm data/raw/*.csv
rm data/raw/measurement-01.csv data/raw/measurement-02.csv data/raw/measurement-03.csv
```

The second line is the exact form of the command that will run. Putting `echo`
before a deletion command and reading the output lets you see a misspelled pattern
before paying its price. Running a destructive command this way once is a
one-step check that should become a habit.

Testing the pattern with `ls` does the same job and also verifies that the files
actually exist.

The shell's word-splitting rule becomes critical here. If `rm data/raw/*.csv` is
mistakenly written as `rm data/raw/* .csv` — a space between the star and the dot —
the pattern matches every file and the directory is emptied. The difference between
the two commands is a single space; the `echo` pre-check shows this difference
before it produces a result.

`rm` offers two confirmation options for interactive use:

```
$ rm -i normal.txt
rm: remove regular empty file 'normal.txt'? n
$ rm -I *.txt
rm: remove 5 arguments? n
```

`-i` asks separately for every file and is defined in POSIX. `-I` asks once, only
when more than three files are given or `-r` is used; it is specific to GNU tools
and is not found in BSD tools. `-I` is more usable in practice: being asked about
every single file trains the user to answer "yes" automatically, while a single
question is actually read.

## Names Starting with a Dash

Why the `--` separator introduced in the shell lesson is necessary becomes visible
here:

```
$ ls
-log.txt  normal.txt
$ rm -log.txt
rm: invalid option -- 'l'
Try 'rm ./-log.txt' to remove the file '-log.txt'.
Try 'rm --help' for more information.
$ rm -- -log.txt
$ ls
normal.txt
```

The command has taken the argument starting with a dash for an option. Everything
after the `--` separator is always interpreted as a filename; the `./` prefix does
the same job, because the name no longer starts with a dash.

This is not a theoretical problem. A pattern matching such a name can cause a
command to run with unexpected options. In scripts, filenames coming from the user
should always be given after a `--` separator.

## The Most Destructive Form

The `rm -rf` combination deletes everything under the given path, without asking
and without reporting errors. Run on the root directory, it targets the entire
system.

This command has **not been run** in this lesson and must not be tried. Common tool
implementations have a guard for the root directory and the command is refused, but
the guard can be disabled with an option and is not present on every system. The
real danger is not even the root itself: with an empty variable, a line like
`rm -rf "$dir"/` targets the root directory.

In practice, three habits prevent most mistakes of this class.

**Working with a relative path inside the directory instead of an absolute path.**
In the wrong directory, the command either gives an error or affects only a narrow
area.

**Running `echo` before `rm` on lines with variable paths.** If the variable is
empty, this shows up immediately in the output.

**Moving instead of deleting.** Moving content aside before deleting it keeps the
decision reversible; the moved directory is deleted deliberately after a while.

The only reliable system-level way to recover deleted data is a backup. Backup and
snapshot strategies are the subject of the System Administration course; there is
no undo within the scope of this course.

## Summary

- Deletion removes the directory entry and decreases the link count; data is not
  freed until the count reaches zero and no process still holds the file open.
- `rmdir` deletes only empty directories, and this failure is a safety criterion;
  `rm -r` deletes it together with its contents.
- `-f` turns off confirmation and the error for a nonexistent file; it does not
  grant the authority to delete.
- Putting `echo` before a destructive command shows the argument list the shell
  will produce, without producing the result.
- `-i` asks once per file, `-I` asks once for a batch operation; `-I` is not
  portable.
- Filenames starting with a dash are mistaken for options; the `--` separator or
  the `./` prefix removes this.

## Next Step

The definition of deletion left a question open: how can the link count be greater
than one, that is, how can a file have more than one name? The next lesson answers
this question and compares two different kinds of link — the hard link, which
shares the same inode, and the symbolic link, which holds a path string.
