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 * ?

8
  • 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, 2013 at 12:55
  • 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, 2013 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. Mar 25, 2013 at 13:06
  • 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, 2013 at 17:44

4 Answers 4

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.

5
  • Thanks Stephance! I like this recognization of *. I wonder if there is way to achieve this in bash.
    – ct586
    Mar 25, 2013 at 12:59
  • @ct586, see my edit. Mar 25, 2013 at 14:22
  • Great! Thanks for giving me weighty reason to postpone the "I'll try zsh someday" indefinitely (I like Unix not trying to second guess me).
    – vonbrand
    Mar 25, 2013 at 16:05
  • @vonbrand, if you don't like it, setopt rmstarsilent. Mar 25, 2013 at 16:18
  • Impressive! I do need to unalias my rm and add this to my bash configuration file. When (/bin/rm*[\ /]"* "* | /bin/rm*[\ /]*) is added to case block, it can catch /bin/rm * also.
    – ct586
    Mar 26, 2013 at 6:08
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.

5
  • 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, 2013 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, 2013 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, 2013 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, 2013 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, 2013 at 13:26
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.

3
  • 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, 2013 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, 2013 at 13:07
  • Yes, agree. What a tragedy
    – ct586
    Mar 25, 2013 at 13:21
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 *

4
  • 4
    This answer is wrong. The -f option overwrites -i and renders it useless.
    – Marco
    Mar 25, 2013 at 12:30
  • 1
    and using the full path avoids the alias.
    – Tim B
    Mar 25, 2013 at 12:32
  • Thanks, Kotte! But this can not solve my problem just as Maceo and Tim B said.
    – ct586
    Mar 25, 2013 at 12:40
  • yeah, this doesn't help very much if you use absolute paths. But I really wanted to share the teaching of my professor ;)
    – Kotte
    Mar 26, 2013 at 15:56

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .