5 ms·
Unrelated, but it is interesting to me that in some OSs you can make a file named "-rf" and if you "rm *" the filename becomes a switch argument.
by batch12 5y ago
Unrelated, but it is interesting to me that in some OSs you can make a file named "-rf" and if you "rm *" the filename becomes a switch argument.
- pabs3 5y agoThe canonical writeup about this issue is here: https://www.defensecode.com/public/DefenseCode_Unix_WildCards_Gone_Wild.txt https://www.defensecode.com/public/DefenseCode_Unix_WildCard...
- NullPrefix 5y agoWhat do you mean some OSs? It works fine on Linux and bash. With zsh I have to expand the * to make it work.
- ninkendo 5y agoNo OS is special here, nor is ZSH/bash... Tried this with bash on linux: $ touch -- -rf $ mkdir subdir1 $ touch subdir1/test1 $ rm * $ ls -rf $ With zsh it's almost the same, it just warns me first: $ touch -- -rf $ mkdir subdir1 $ touch subdir1/test1 $ rm * zsh: sure you want to delete all 2 files in /path/to/test [yn]? y $ ls -rf $ Since there was a file called -rf, `rm *` expands to `rm -rf subdir1`, and that's what it does. The actual file named -rf survives because -rf was interpreted as an option rather than a filename. It would only have been removed if I did `rm -rf -- *`.
- tgv 5y agoThat's perhaps the slightly wrong way of looking at it. "rm" is an executable that parses its command line; the asterisk is a special symbol that gets expanded to a list of all file names (except those starting with a period). So the arguments `rm` receives when you type `rm *`, is a list of all file names. It does not know that, because all arguments are just strings, and therefore it parses those strings the same way as if they had been typed, which makes that a filename like `-rf` can trigger the behavior of the "flag" `-rf`.
- mananaysiempre 5y agoAre there any (Unix-likes) where you can’t? Aside from degenerate cases like Windows SFU/SUA (though I’d expect that one to allow it as well). Globs getting interpreted as switches is a very unfortunate footgun, sure, but I don’t see how you could eliminate it while retaining the same level of smarts in the shell (tokenization but only into dumb strings), and DOS/Windows command line parsing is IMO essentially a reductio ad absurdum for the idea of having less (no tokenization, but the shell still splits commands). Except maybe require the -- between switches and arguments whenever there are arguments? But not only is that an incomplete fix, it also goes contrary to convenience of interactive usage, which is important: much of the tension in shell syntax and Unix utilities is due to balancing it with conventional programming, I feel, and I wouldn’t want to be writing even Perl or Tcl instead, let alone Powershell or the like.
- batch12 5y agoMaybe. I hedged my statement with the weasel word "some" since I haven't used many Linux flavors and I anticipated someone coming back with 'BeaspokeLinux doesn't do this!!'. For what it is worth, it has been All that I have used...
- FeepingCreature 5y agoFor a similar reason, `touch ~/-i` can protect you from some problematic `rm -rf *`s.
- wruza 5y agogetopt-like libs stop parsing options after “--“, so “rm -- *” should be safe, afair.
- im3w1l 5y agoUsing double-dash solves almost all such issues. One notable exception: a file named dash will still be interpreted as stdin. echo a > - echo b | cat -- - Output: b