# safe-rm turns rm into a move to the system trash

> safe-rm is a shell wrapper that intercepts rm and moves files to the system Trash instead of unlinking them, supporting most of the original options and following the FreeDesktop trash specification on Linux. It suits people who delete the wrong file, and it cannot replace rm in scripts that depend on unlinking or on error codes.

**kaelzhang/shell-safe-rm** — 😎 Safe-rm: A drop-in and much safer replacement of bash rm with nearly full functionalities and options of the rm command! Safe-rm will act exactly the same as the original rm command.

- Repository: https://github.com/kaelzhang/shell-safe-rm
- Stars: 619 · Forks: 35
- Language: JavaScript
- License: NOASSERTION
- Published: 2026-10-22 · Updated: 2026-10-22 · Language: en
- Canonical page: https://hysenlabs.com/projects/kaelzhang-shell-safe-rm

## A wrapper that answers to rm

safe-rm is described as a drop-in and much safer replacement for the unix rm command, with almost full features of the original rm. The mechanism is a shell alias rather than a reimplementation of the kernel interface. You install a script and then point rm at it, so that the command you type is intercepted before it reaches the real binary. That design has one large advantage and one large cost, and both are worth naming before anything else. The advantage is that it is transparent to the person typing: there is no new verb to learn, and the muscle memory of rm keeps working. The cost is that anything which does not go through your interactive shell, a script, a cron job, a Makefile rule, a container entrypoint, will still call the real rm and get the old behaviour with none of the protection. The project was initially developed on Mac OS X and has been continuously used by the author since then, with later testing on Linux, and the features list claims support for both platforms with full test coverage.

## What actually happens to the file

The core promise is that files and directories you choose to remove are moved to the system Trash instead of simply being deleted, and that you can put them back manually whenever you want. The mechanism differs by platform, and the differences are the interesting part. On macOS, safe-rm uses AppleScript to delete files or directories as much as possible, specifically so that the built-in Put Back capability in the system Trash bin works. On Linux it follows the operating system's conventions for handling duplicate files in the Trash, so a second file with the same name does not overwrite the first. Linux also creates a FreeDesktop style .trashinfo file alongside the moved item, which is what makes the desktop trash's Restore function able to put an item back where it came from. On macOS the path is either AppleScript through Finder or a plain mv, and which one you get depends on configuration, with the restore table in the documentation making the outcomes explicit.

## The supported option set, and what was deliberately left out

For the options it implements, safe-rm is documented to act exactly the same as the original rm. That covers -i and --interactive for a confirmation prompt before each file, -I for prompting only once when removing more than three files or removing directories recursively, -f for removing without prompting while ignoring nonexistent files and overriding file protections, -r and -R and their long forms for recursive removal, -v for verbose output, -d for removing only empty directories, and the -- end of options marker for filenames that begin with a dash. Combined short options are supported, with -rf, -riv and -rfv given as examples. The interesting part is what is not supported. The BSD-only options -P for overwrite, -W for undelete and -x for not crossing mount points are intentionally excluded, because they have no meaning for a trash-based tool, and the documentation notes that safe-rm reports them as an illegal option rather than silently ignoring them. That is the right call, since a silently ignored -f would be far worse than a rejected one.

## Installing by npm, by source, or as an alias to a clone

The usual installation is a global npm package.

```sh
npm i -g safe-rm
```

The alternative is to work from the source in the repository, which the documentation marks as not recommended because it may be unstable.

```sh
# If you have NodeJS installed
npm link

# If you don't have NodeJS or npm installed
make && sudo make install

# For those who have no `make` command:
sudo sh install.sh
```

The Makefile is trivial and shows where things land: the install target copies bin/rm.sh to /bin/safe-rm and chmods it to 755, then prints a reminder to add the alias to your ~/.bashrc. There is also a lighter path for people who do not want to install anything system wide, which is to clone the repository and alias rm to the script in the clone.

```sh
alias rm='/path/to/bin/rm.sh'
```

Either way, the alias is the part that makes it effective, and it has to be added to every shell session where you want the protection, not just the one you configured it in.

## Confirming the wrapper is the one answering

There is a small but useful verification step in the documentation, and it is the kind of detail that separates a careful tool from a careless one. After installation and alias definition, running rm with no arguments prints the safe-rm name followed by the usage line, which is how you tell safe-rm apart from the original rm.

```sh
$ rm
safe-rm
usage: rm [-f | -i] [-dPRrvW] file ...
     unlink file
```

The usage line is worth reading on its own, because it is a summary of what the tool actually supports. Note that the usage string still shows the -P, -R and -W letters even though the documentation says BSD-only options are rejected, so the usage text is not a complete description of the accepted option set. The test suites in the package manifest give a sense of how the behaviour is pinned: separate ava suites cover the rm behaviour, running the tool as another user, the Linux per-mount behaviour, and a safety suite, with a debug mode driven by SAFE_RM_DEBUG and a mocked Linux mode driven by SAFE_RM_DEBUG_LINUX.

## Configuration file, trash location and the Put Back trade-off

Since version 3.0.0 there is a configuration file at ~/.safe-rm/config in your home directory, and it controls three things: a custom trash directory, whether safe-rm may permanently delete items that are already in the trash, and whether AppleScript may be used on macOS. The sample file ships in the repository and can be copied into place.

```sh
# You could
cp -r ./.safe-rm ~/
```

A different configuration file can be pointed at through the SAFE_RM_CONFIG environment variable, wrapped in an alias if you want a per-profile behaviour.

```sh
alias="SAFE_RM_CONFIG=/path/to/safe-rm.conf /path/to/shell-safe-rm/bin/rm.sh"
```

Or if it is installed by npm:

```sh
alias="SAFE_RM_CONFIG=/path/to/safe-rm.conf safe-rm"
```

The macOS trade-off is the one to read twice. By default AppleScript is used as much as possible so that removed files can be put back from the system Trash app, and you can turn that off with SAFE_RM_USE_APPLESCRIPT=no. Setting a custom SAFE_RM_TRASH has the same effect, because a custom trash path makes safe-rm move files with mv instead of AppleScript, which disables the Finder Put Back capability. You can still drag items back manually, but you lose the metadata that tells the system where the file came from. On Linux, the mechanism is mv plus a .trashinfo file, which the desktop trash Restore function can use, so the restore story is intact there without AppleScript.

## Where safe-rm is the wrong tool

There are situations where replacing rm with a trash move is actively wrong, and the documentation is clear enough to reason from. A build script that removes a directory and expects it to be gone will leave it in the trash, and a later step that creates a file with the same path will fail. A container image build has no user trash to move things into, and moving files there gains nothing. A cleanup job that runs daily to reclaim disk space will accumulate the same files in the trash instead. And the exit codes change meaning: rm reports an error for a missing file, while a trash-based move has its own behaviour, so a script that checks for failure will not see what it expects. The alias also has a scoping problem that no amount of configuration fixes, because scripts do not read your ~/.bashrc. If your goal is to make one dangerous command recoverable for yourself, safe-rm is a good fit. If your goal is to make deletion safe across a fleet of machines and pipelines, this is not the mechanism for it.

## Conclusion

Adopt safe-rm if you are the kind of user who has deleted a file they needed, and you want that mistake to be recoverable from a trash bin rather than final. Do not adopt it in scripts, in containers where no trash exists, or in any workflow that depends on rm failing with a non-zero exit when a file is missing, since the semantics deliberately differ. Verify two things before you alias it over rm: that you understand the restore behaviour on your platform, because a custom SAFE_RM_TRASH on macOS gives up the Finder Put Back function, and that the alias is in place in every shell you use, since the alias only covers the shells where it is defined. The practical first step is npm i -g safe-rm, add alias rm='safe-rm' to your ~/.bashrc, and then confirm that a bare rm prints the safe-rm usage line so you know the wrapper is the one answering.

## FAQ

### How do I install safe-rm?

The recommended route is npm i -g safe-rm, which puts the safe-rm script in your /bin directory. You can also use npm link or make and sudo make install from a source checkout, or sudo sh install.sh if you have no make command.

### How do I make safe-rm act as rm?

Add an alias to your ~/.bashrc script, either alias rm='safe-rm' for the npm install or alias rm='/path/to/bin/rm.sh' for a local clone, and define the same alias in every open terminal session.

### Can I restore a file deleted with safe-rm?

On macOS the default system trash uses AppleScript through Finder, so the Put Back function works. On Linux, safe-rm uses mv plus a FreeDesktop .trashinfo file, so the desktop trash's Restore function works. A custom SAFE_RM_TRASH, SAFE_RM_USE_APPLESCRIPT=no or a symlink target on macOS falls back to mv and loses the metadata for restoring.

### Which rm options does safe-rm not support?

The BSD-only options -P for overwrite, -W for undelete and -x for not crossing mount points are intentionally not supported because they have no meaning for a trash-based tool. safe-rm reports them as an illegal option rather than ignoring them.

### How do I uninstall safe-rm?

Remove the alias rm=... line from your ~/.bashrc file first, then run npm uninstall -g safe-rm, or make and sudo make uninstall, or sudo sh uninstall.sh. The Makefile's uninstall target also reminds you to unalias rm in your open terminal sessions.

## Sources

- [Issues](https://github.com/kaelzhang/shell-safe-rm/issues)
- [kaelzhang/shell-safe-rm on GitHub](https://github.com/kaelzhang/shell-safe-rm)
- [README](https://github.com/kaelzhang/shell-safe-rm/blob/master/README.md)
- [Releases](https://github.com/kaelzhang/shell-safe-rm/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/kaelzhang-shell-safe-rm
