Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

Is there a Linux script / application which, instead of deleting files, moves them to a special “trash” location? I’d like this as a replacement for rm (maybe even aliasing the latter; there are pros and cons for that).

By “trash” I mean a special folder. A single mv $* ~/.trash is a first step, but ideally this should also handle trashing several files of the same name without overwriting older trashed files, and allow to restore files to their original location with a simple command (a kind of “undo”). Furthermore, it’d be nice if the trash was automatically emptied on reboot (or a similar mechanism to prevent endless growth).

Partial solutions for this exist, but the “restore” action in particular isn’t trivial. Are there any existing solutions for this which don’t rely on a trash system from a graphical shell?

(As an aside, there have been endless discussions whether this approach is justified, rather than using frequent backups and VCS. While those discussions have a point, I believe there’s still a niche for my request.)

share|improve this question
3  
This may be related to the SuperUser question Two commands to move files to trash. What's the difference?. I've used gvfs-trash in the past, but never had a need to restore from the command-line until you sparked my curiosity. The answer to the linked question may be of help. –  ephsmith Jul 10 '12 at 23:02
1  
@ephsmith Thanks, good link. The problem with those approaches though is that they are bound to specific desktop shell (what’s the correct term here?) implementations, something which I want to avoid. –  Konrad Rudolph Jul 11 '12 at 9:32
    
Is moving files from any filesystem to your ~ intentional? Because some day you might be deleting a 4GB iso image residing on a dir mounted with sshfs from a really remote server. –  Mischa Arefiev Jul 11 '12 at 11:40
    
@Mischa To be honest, I didn’t put that much thought into it. That said, it should work with the usual user’s rights, so the target needs to be a location that is writeable and shouldn’t require too much configuration. –  Konrad Rudolph Jul 11 '12 at 11:43
    
Do whatever you want such as the solutions outlined in the answers below, but don't name it rm. As pointed out by others, renaming/repurposing standard commands leaves you vulnerable when you habitually try to use them on other systems, but it also will cause problems for anyone else (perhaps assisting you) using your system/account when unexpected results occur. –  Joe Jul 14 '12 at 20:43

5 Answers 5

up vote 8 down vote accepted

There is a specification (draft) for Trash on freedesktop.org. It is apparently what is usually implemented by desktop environments.

A commandline implementation would be trash-cli. Without having had a closer look, it seems to provide the funtionality you want. If not, tell us in how far this is only a partial solution.

As far as using any program as replacement/alias for rm is concerned, there are good reasons not to do that. Most important for me are:

  • The program would need to understand/handle all of rm's options and act accordingly
  • It has the risk of getting used to the semantics of your "new rm" and performing commands with fatal consequences when working on other people's systems
share|improve this answer
    
There is also libtrash which moves all deleted files automatically to the trash via LD_PRELOAD (but it seems to have several bugs). Autotrash helps to clean the trash in an easy way. –  jofel Jul 11 '12 at 8:47
    
I’m wondering about the getting-in-the-habit-of-using-rm thingy. I’m already in the habit, unfortunately. –  Konrad Rudolph Jul 11 '12 at 9:43
    
@jofel: libtrash has a really nice concept. A few layers deeper than the other approaches. It's a pity it is buggy (and does not seem very active). –  zpea Jul 11 '12 at 10:29
2  
@KonradRudolph: I meant that one gets used to the fact that rm (the replaced one) does not really delete anything, so that one is less careful, as a restore is always possible. Of course, using rm itself is not a bad thing, nor is getting used to it. –  zpea Jul 11 '12 at 10:33
    
I’ve ended up using this solution, and disabling rm so I can’t use it accidentally (there’s still /bin/rm in case I really need it). –  Konrad Rudolph Sep 5 '12 at 8:16

Here's a quick and dirty trash system that copes with name clashes and even allows multiple deleted files on the same path as long as you don't delete more than one file per second.

Warning: I typed this code directly into my browser. It's probably broken. Don't use it on production data.

trash_root=~/.trash
mkdir "$trash_root"
newline='
'
trash () (
  time=$(date +%Y%m%d%H%M%S)
  for path; do
    case $path in /*) :;; *) path=$PWD/$path;; esac
    mkdir "$trash_root${path%/*}"
    case ${path##*/} in
      ?*.*) ext="${path##*.}"; ext="${ext##*$newline}";;
      *) ext="";;
    esac
    metadata="Data: $hash.$ext
Date: $time
Path: $path
"
    hash=$(printf %s "$metadata" | sha1sum)
    printf %s "$metadata" "$trash_root/$hash-$time-metadata"
    mv "$path" "$trash_root/$hash.$ext"
  done
)

untrash () (
  IFS='
  '
  root=$PWD
  cd "$trash_root" || return 2
  err=0
  for path; do
    if [ -e "$path" ]; then
      echo 1>&2 "Not even attempting to untrash $path over an existing file"
      if [ $err -gt 2 ]; then err=2; fi
      continue
    fi
    case $path in /*) :;; *) path=$root/$path;; esac 
    if metadata=$(grep -l -F -x "Path: $path" *-metadata |
                  sort -t - -k 2 | tail -n 1); then
      mv "${metadata%%-*}".* "$path"
    else
      echo 1>&2 "$path: no such deleted file"
      if [ $err -gt 1 ]; then err=1; fi
    fi
  done
  return $err
)

Known issues:

  • Doesn't cope gracefully if you try to delete the same file several times concurrently.
  • The trash directory may become huge, the files should be dispatched into subdirectories based on the first few digits of the hash.
  • trash should cope with newlines in file names, but untrash doesn't because it relies on grep and the newlines are not escaped in the metadata file.
share|improve this answer

There's a little utility called rmtrash which does this.

It doesn't seem to respond to params like -r or -f (it appears to essentially just be moving the file/directory to the ~/.Trash directory), but it won't override files with the same name (it appends "Copy" to like-named files/directories).

To install with brew

brew install rmtrash
alias rm='rmtrash' >> ~/.bashrc
share|improve this answer

Start by defining a move_to_trash function:

move_to_trash () {
    mv "$@" ~/.trash
}

Then alias rm to that:

alias rm='move_to_trash'

You can always call old rm by escaping it with a backslash, like this: \rm.

I don't know how to make the trash directory empty on reboot (depending on your system, you may have to look into the rc* scripts), but it could also be worthwhile to create a cron task that empties the directory periodically.

share|improve this answer
2  
Unfortunately, that was the easy part … :/ –  Konrad Rudolph Jul 10 '12 at 22:11
    
This script could also create a text file in a hidden directory for each file which contains the directory it was in. A restore script could read the old location and move it back. –  ephsmith Jul 10 '12 at 22:20
    
This also has a hazard of multiple deleted files with the same name would collide in the trash directory, and only the last one "deleted" would survive to be able to be recovered. –  killermist Jul 10 '12 at 23:05
    
@killermist, yes. Of course one would need to do something additional with the move command. Name the "trashed" file whatever you want and keep the original path :| This all screams "why re-create the wheel". There are existing solutions to this problem. –  ephsmith Jul 11 '12 at 0:47
    
Also, use a different alias name. Work on another machine without your aliases, one call to rm and there go your files. del might be a better choice. –  glenn jackman Jul 11 '12 at 0:51

trash-cli is a command Line Interface to FreeDesktop.org Trash. So, it trashes files recording the original path, deletion date, and permissions. It uses the same trashcan used by KDE, GNOME, and XFCE, but you can invoke it from the command line (and scripts).

  • Can I alias rm to trash-put?

You can but you shouldn't. In the early days I thought it was good idea do that but now I changed my mind. The interface of trash-put seems to be compatible with rm it has a different semantic that will cause you problems. For example, while rm requires -R for deleting directories trash-put does not.

Copied from and read more about it in https://github.com/andreafrancia/trash-cli

This is already packaged in Debian and Ubuntu (at least), so you can install it with aptitute install trash-cli.

share|improve this answer
    
This is essentially the same as the accepted answer, isn't it? –  Konrad Rudolph 15 hours ago

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.