6

I cannot remember how many times I've listed a subdirectory and executed /bin/rm -f * in the current directory. Can anyone give suggestions to help me avoid this? What should I do if I want the system to warn me of the danger when I try to execute /bin/rm -f * ?

ct586
  • 85
  • 4
    Why do you use the full path in the first place if you are unsure? The full path to the rm binary in combination with the -f flag is a strong indicator that you really want to delete the files. You should change your habits and not your system. – Marco Mar 25 '13 at 12:55
  • I agree Macro. Maybe I should change the habit. I use /bin/rm -f just because my rm is an alias of mv. I should take care of this. – ct586 Mar 25 '13 at 12:57
  • 2
    Your comment illustrates the issue with using aliases to guard against dangerous rm usage. You already have one set up, and went on to develop the habit of using the full path to avoid the aliased command. I do the same thing, with rm aliased to "rm -i". When I want normal behavior, I type "\rm" instead, but when doing that I accept that I am running a normal rm. – Tim B Mar 25 '13 at 13:04
  • 4
  • 1
    Make backups. And stop using aliases for rm and the like, it will screw you over whenever you're using a different machine. Also you can use \rm to circumvent the alias. – frostschutz Mar 25 '13 at 13:06
  • Thanks all! I will take your suggestions and take care for all my commands. – ct586 Mar 25 '13 at 13:11
  • 2
    If you find yourself getting into the habit of working around your alias, then your alias is too intrusive and should be replaced with one that's still safe, but less annoying. What exactly is your "alias of mv"? – Random832 Mar 25 '13 at 17:44
  • alias rm=trash trash() { mv -i $@ ~/.cttrash/ } Usually I will use rm to mv small files to a trash. Then delete all of them timely. – ct586 Mar 26 '13 at 01:16

4 Answers4

9

zsh by default asks you for confirmation, when you try and run any command called rm with * as a whole word on the command line (a feature inherited from tcsh though in tcsh it's not enabled by default).

$ rm -rf *
zsh: sure you want to delete all the files in / [yn]?

If you have to use bash, with recent versions of bash, you could do something approaching by using extdebug and the DEBUG trap:

shopt -s extdebug
check_for_rm_star() {
  case $1 in
    (rm*[\ /]"* "* | rm*[\ /]\*)
      read -p "check_for_rm_star: Are you sure? " -n1 answer < /dev/tty > /dev/tty
      echo > /dev/tty
      [[ $answer == [yY] ]]
  esac
}
trap 'check_for_rm_star "$BASH_COMMAND"' DEBUG

That's a simplistic one that would work for rm * and the most common cases but not for instance for rm "*" or /bin/rm * or : $(rm *), but you get the idea. Ideally, we'd need to parse $BASH_COMMAND the same was as the shell does to see if the first argument expands to rm or */rm, and to see if it's passed an unquoted *, but that can't really be done in a bulletproof fashion.

2

The only way to do that is to replace rm itself.

There is a wrapper script for rm that purports to provide a safe rm, which can be found at LaunchPad. From that page:

Safe-rm is a safety tool intended to prevent the accidental deletion of important files by replacing /bin/rm with a wrapper, which checks the given arguments against a configurable blacklist of files and directories that should never be removed.

The only issue I see with that is your example "dangerous" rm example is run with the full path, /bin/rm. So you couldn't put this wrapper script in a directory earlier in your $PATH, and let it get found when you run rm, and have the unwrapped "normal" rm available by typing the full path, /bin/rm, as you do above.

Anthon
  • 79,293
Tim B
  • 781
  • Thanks Tim! This could be a great way to protect system files. However, the blacklist for personal usage could be very large and flexible. – ct586 Mar 25 '13 at 12:49
  • It's just a perl script. You customize it into any behavior that suits you. But as others have pointed out, you used an alias to make rm safer, but then developed the habit of typing the full path /bin/rm explicitly to avoid that safety net. – Tim B Mar 25 '13 at 13:07
  • Yes, agree. What a tragedy – ct586 Mar 25 '13 at 13:21
2

One possibility is to create a shell alias to map rm to a less destructive command. For instance:

alias rm='trash'  # from the package trash-cli

This does not delete the files, but places them in the trash bin, so you can restore them. However, this changes the semantics of the rm command (you can delete entire directories without -r, for example). Furthermore, it does not help if the full path is used.

Another possibility is to set up a regular backup, say once per hour. That way you can happily delete files and restore them later.

Marco
  • 33,548
  • 1
    The problem with aliases is that that they don't get used if you type the full path to the command, as the OP does in his example. To guard against that, you really do need to replace /bin/rm with something else. And on a system used by others, that could be unacceptable. (it would be to me.) – Tim B Mar 25 '13 at 12:35
  • You're totally right. But if someone requests /bin/rm (s)he expects rm with the known semantics. I would never replace rm system-wide. If that's really an issue for several users (a single user can always create a local rm and adjust the PATH) I would consider a frequent backup and let the users learn the hard way that rm deletes files. – Marco Mar 25 '13 at 12:40
  • Thanks Marco! I have already set this for my regular usage. Sometimes I want to execute /bin/rm -f * and also I want a hint to tell me "Are you sure?". – ct586 Mar 25 '13 at 12:45
  • The backup system will reduce the loss of misoperation. I have a backup system for other folders but not this one. Maybe I should backup this also. – ct586 Mar 25 '13 at 12:51
  • If you want the asterisk to trigger some unique behavior, only the shell can do that. (Globbing must occur prior to exec) If that feature is something you want, then as Stephane notes, switching to zsh is one way to get it. It is still a bourne-ish shell, so it might not feel too alien. – Tim B Mar 25 '13 at 13:26
0

One simple solution is to add the alias rm="rm -i", then you will get asked before each removal if you are sure. But, as pointed out by one of my teachers, this might fool you that the unix system you are using is a safe and warm place, and that might be even more dangerous than accidentally running rm *

Kotte
  • 2,537