How do I prevent accidental rm -rf /*?
serverfault.com
serverfault.com
When you have strong permissions (e.g. running as "root"), you should never use patterns in destructive commands, period.
At best, you should perform a nondestructive pattern command such as a "find" and generate a precise list of target files that can be audited. For example, here is one way to produce a script of commands that deletes an exact list of matching files:
find * | awk '{print "rm \047"$0"\047"}' > delete.sh && chmod +x delete.shGuis know this, but somehow this piece of UX is forgotten on command line tools.
Just because you protect one "rm" command doesn't mean there isn't another. Someone might have used unlink() in a Perl script or a C program. Maybe "mv" was used to write one file over another, or "cat >! filename", or a dozen other things.
In the end, if a file needs to be safe then it needs a backup (and the sooner it can be restored, the better). And then given a good backup the file still needs an appropriate Unix group, owner, file access control list, etc. to minimize the chance that you'll ever need the backup.
Because command line tools were first, and are used by people who do need to remove files, to clear disk space.
If you're never deleting anything, how do you clear disk space?
Well, I have done stupid things myself, for example typing "rm -rf / some_dir" instead of "rm -rf /some_dir". I noticed because it was taking a wee bit too long. It is always good to do an ls with the intended pattern first, to check what all files and directories are being matched before invoking rm with the same pattern.
you can even do a ls -rf ./somedirectory and then just do ^ls^rm at least you can in bash on os x.
On company I contracted for had something clever going on. Not only did they litter -X files everywhere, attempting to remove one (rm -- -X) would result in an access violation of some kind and your session would be killed as a result, preventing a recursive rm from continuing.
People alias -i and forever supply -f. That doesn't do any good at all. The real answer is to be more careful. It eventually becomes habitual. In about 15 years I have lost data to rm twice: the one time I mistakenly removed the wrong folder, and once when I thought I had a copy of the data.
Two: don't pass -f. Do you even know what -f does, or are you just cargo-culting it? If you need -f, rm will tell you. Don't use it until then.
Some solutions here center on avoiding issuing rm -rf /* interactively... that's not enough! A broken script or unexpected variable expansion can wreak just as much havoc.
For example rm -rf $SOMEDIR/* :
- if $SOMEDIR is empty, or
- (if you suffer from bash) if $SOMEDIR contains trailing space so it will be expanded into separate words: SOMEDIR='foo '; rm -rf $SOMEDIR/* => rm -rf foo /* (which means, `remove ./foo and remove /* ')
An alias won't help if full path to command is specified; that is quite common for start-up scripts.
I have experienced consequences of rm -rf /* once or twice. Now I pause for a moment every time I am about to remove something and double-check the command. Sometimes even prepend `echo' for a dry run ;-)
Edit:
another nasty case of unintended deletion I had was due to a dumb Makefile rule:
$(CC) -o $(OUTFILE) $(INFILE)
for some reason $(OUTFILE) ended up empty, so outupt went to $(INFILE) -- a C source file -- effectively removing its content. How would I guard against that kind of data loss? A snapshotting filesystem...There should be a name for that.
Not that I have had to use it.
I am also very happy with myself for putting my most important files in Dropbox, so it is semi-idiotproof.
appropriate countermeasures imho:
1. run an account with the right amount of access.
2. don't use sudo. (su + password makes you think a bit more)
3. this sounds dickish, but I mean it constructively. Pay attention. the -f flag means something...
4. when all else fails, rsync'd folders are a beautiful thing :)
"We stand upon the brink of a precipice. We peer into the abyss—we grow sick and dizzy. Our first impulse is to shrink away from the danger. Unaccountably we remain... it is but a thought, although a fearful one, and one which chills the very marrow of our bones with the fierceness of the delight of its horror. It is merely the idea of what would be our sensations during the sweeping precipitancy of a fall from such a height... for this very cause do we now the most vividly desire it."
Edgar Allan Poe - The Imp of the Perverse
1. Backups 2. Sudo
I rarely do anything as root. If I am switching to root I already know what command I want to run. Backups are for when I do something stupid.
It's not quite applicable to something used as off-handedly as rm, though it could be done. Something like:
make-rm -rf /*
might produce output like: rm /usr/bin/a
rm /usr/bin/b
# ...
rmdir /usr/bin
rm /usr/lib/a
#...
And so on. That can then be piped to bash as a confirmation. rm -rf ./*
instead of just: rm -rf *
Is there a difference between the two that I'm not aware of? ./*
expands to ./-filename
which won't be picked up by option processing. Note: You can also do rm -rf -- *
to prevent option processing after the '--'.edit: added a bunch of breaks to prevent the * from being converted to italics.
The difference is in glob expansion: ./* keeps the prefix on every expanded item. As mentioned above, using any sort of path (relative or absolute) prefix when globbing will circumvent all the careful "-i" wards a superstitious sysadmin may have put in place.
And how can you detect /* if the shell expands it?
I think I rarely use rm -r with an absolute path. And tab completion does something similar (list your targets) if you don't jump the gun with <enter>.
PS I'm entirely comfortable with my Alt-B as "rxvt -e 'sudo zsh'".
find . -name "whatevs"
hit enter, verify you are deleting what you expect then hit the up arrow and type:
| xargs rm -rf
find . -iname "whatever" -delete
Otherwise you're screwed if someone managed to put a file named "/" somewhere in your find directory, which `-delete` has safe-guard for.If I would have hit Return to soon it would have bailed out automatically.
Worked well on Redhat Linux, unfortunately it doesn't work on my Mac these days...