Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

My good old trick to mitigate that is:

    touch /-@
I also always do it in my home directory:

    touch ~/-@
That's the first thing I do on a new host.

When accidentally running rm -f *, the command expands to -@ first, which is not a valid option and makes the command fail before doing any harm

    rm: illegal option -- @
    usage: rm [-f | -i] [-dPRrvW] file ...


While this is a really nice hack, stuff like this is also the reason I feel really uneasy when writing shell scripts. What works now may suddenly break in the future due to inadequate escaping of filenames.


That won't actually help with rm -rf /* , only with rm -rf * in / or $HOME.


Would it work with `touch "/ -@"` (not the space)?


No, it doesn't work. "./*" expands to "./ -@" as a single field, which rm has no problems with. (Note that, however, this is still the globbing of the shell, as far as I understand.)


how would changing the filename fix it? it's a hack relying on the globbing of the shell. if you're not using the globbing, the hack can never help you.


Very handy trick. More so if no root access, myself I preer to rename rm and drop a shell wrapper in place and can be simply a case of changing all passed "" into "Sorry_Dave_I_can_not_allow_you_to_do_that" (or words to that effect) and all "-AsteRISKdeleteALL" into "-" and then that modified input is passed onto rm. But can adjust how and add rules to taste.

That way the pain of having to type AsteRISKdeleteALL instead of * for rm events offsets any anxiety by far.

You can also catch the rm and mv to a difectory with quota's you can call a recycle bin, some low end attached storage can be fine as well as not many situations when your wildcard deleting with a time factor. Can accommodate this in your own skulker to clean up in a more organised way overall in a timely manner. and and scripts you can path to the real rm command if needs be, last time I called it P45Generator, but not the finest for readability in any such scripts.


As someone who uses the commandline a lot but isn't exactly a wizard, why does this work?


globbing expression expand to all the files that match.

if a directory has 1.txt, 2.txt, and 3.txt then << rm * >> expands to "rm 1.txt 2.txt 3.txt" and is then executed.

if you have -@, 1.txt, 2.txt, and 3.txt, that expands to << rm -@ 1.txt 2.txt 3.txt >>, and that can't execute.

(if you really wanted to remove your -@ you'd do << rm -- * >> because a double-dash signals the end of command-line options.)


The * is expanded by the shell to a space-delimited list of filenames, but the shell does not adequately escape filenames that can be misinterpreted as arguments to 'rm'.


That's kind of scary — in that case I guess I should avoid creating a file named -rf.


Yes. There was an article linked from HN ages ago (at least a year) that went into mitigation techniques for these issues. As you expect, it basically became fractal, and even then still had bugs. I wish I still had the URL.


I think it may be more scary for code that allows arbitrary execution using command-line arguments. Commands like find or xargs using without defense against this would be a problem. For example, site that does something precious with your uploaded pet pictures.

Defending against this being the use of -- to signal an end of command line arguments.


That is really interesting.

Can someone knowledgeable about the shell expand on this? I don't dare test it on my machine.


Shell session to demonstrate (DO NOT DO IT IN THE DIRECTORY WITH IMPORTANT FILES):

  $ touch important
  $ chmod 400 important
  $ rm *
  override r--------  vbezhenar/staff for important? n
  $ touch -- -rf
  $ ls -l
  total 0
  -rw-r--r--  1 vbezhenar  staff  0 Mar 24 14:35 -rf
  -r--------  1 vbezhenar  staff  0 Mar 24 14:35 important
  $ rm *
  $ ls -l
  total 0
  -rw-r--r--  1 vbezhenar  staff  0 Mar 24 14:35 -rf
  $ rm -- -rf


I've not tested it, but it should expand just like anything else. The effect would broadly be that running "rm *" in the directory would recurse into subfolders without warning.


Re testing. If you follow this link - https://www.digitalocean.com/?refcode=3fc9a5a35c52 - you get $10 free credit (affiliate link I get $25 if you spend that much in future) on DigitalOcean.

You can spin up a droplet and use the online shell tool or ssh in (very easy when you've set up a cert as the droplet can have the cert setup automatically).

Then you can mess about with a droplet as much as you like, virtually speaking. Once you're done then use the control panel to destroy the droplet - it costs a few ¢ a day and if you don't have a droplet in use (which means active or paused; preserving images is cheaper but non-zero) then you don't pay anything.

Basically sign up and have a year of uptime to mess with a full install of various OS with no charge.

Make sure you don't write "rm -rf /*" in the wrong terminal!


> shell does not adequately escape filenames that can be misinterpreted as arguments to 'rm'

That sounds like a bug to me, or at least depending on suboptimal behavior.


More specifically, it is expanded on the shell

Example:

$ echo /*

/bin /boot /dev /etc /home (...)


Hm that's a cool trick. IIRC some distributions (Suse?) had a 'bash' clause where you couldn't do "rm -rf /" without 'y'.

My 'zsh' has this one too, when I 'rm -rf /some/dir/' always asks if I'm "sure". Truth to be told, I'm not even expecting the text in "stdout" anymore, my finger goes to the 'y' automatically, which means that if I make something stupid it won't be able to protect me :-P

The last couple of years I stopped doing 'stupid things' by stop working on the shell when I'm very tired. That was the cause of my rm-related-incidents in the past :-)


Some versions of RM (Ubuntu/Debian if I remember correctly) require --no-preserve-root.


Likely you mean: touch ~/-@


Neat idea! Just tested that in an OS X 10.8 virtual machine; while it works nicely against "rm -rf *", sadly it does not help stop an accidental sudo rm -rf / or ~/. Also, "touch ~-@" created a file in the home directory called "~-@"; in order to set the correct filename, I cd'd into ~ and then ran "touch ./-@".


  touch /--
  rm -rf *
(admittedly, this would be a malicious attempt rather than a careless bug)


Or just use zsh.


Would zsh still protect me if the script explicitly uses Bash (i.e. #!/bin/bash)? Sorry if this is a dumb question, I'm unsure how shells work when calling other kinds of shell scripts.


No. If the script has the #! set as /bin/bash, then it will run as bash.


zsh is an interactive shell. It is not to replace #bash as system shell as I know.


Zsh doesn't have to be used interactively.

It's also excellent for scripting, and has far more features than bash.


alias rm='trash-put'


rm -rf -- $EMPTY_VAR/*

Ooops.




Consider applying for YC's Fall 2026 batch! Applications are open till July 27.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: