# Can I make rm interactive only when using globbing? (in either bash or zsh or both)

Whenever I rm multiple items at once with shell globbing and there's even the slightest possibility that the pattern expands to more than I expect it to, I always try to remember to add -i, but (of course) I could forget and accidentally blow away something useful. Some people try to solve this problem with an alias, such as alias rm='rm -i' but I hate the idea of making rm always interactive, because then I'll get into the habit of using -f all the time, which will obviously defeat the whole purpose.

What I'd like to do is make rm only use -i when I use globbing, and for -f of course to override -i, so I can still blow away whole directories with the usual rm -rf junk.

Therefore rm *blah* would really be rm -i *blah* but rm blah would work exactly as typed.

In case there's a difference in how this might be accomplished in different shells, I will chose an answer that supplies methods for both bash and zsh over answers that only cover one or the other.

Note: I'm not actually convinced this is necessarily a good idea; I'm just asking if it is possible. If you think this is a stupid idea, I would be very happy to hear the reasoning behind your opinion, but please don't post such comments in the answer field. Real answers either tell me how to do this or explain that/why it is not possible (or possibly offer an alternative method to getting a similar result). But if you want to tell me why this is dumb, please post as a comment. I'll upvote well-reasoned comments even if I disagree with the conclusion.

-
A few suggestions: with GNU utilities, rm -I is like -i that only triggers when more than three files or -r is passed. In bash, use Ctrl-x * keyboard shortcut to expand the glob and inspect it yourself. –  jw013 Aug 28 '12 at 17:26
With bash, I believe the answer is "no". With zsh, you might be able to take advantage of noglob by e.g., aliasing rm to noglob my-rm, and then having my-rm be a script that checks for a glob, expands it, and passes -i or not. Not sure, don't know zsh. –  derobert Aug 28 '12 at 17:44
@derobert: you certainly sound like you know zsh pretty well. –  iconoclast Aug 28 '12 at 17:56
@iconoclast Nope, not zsh, just Google. Oddly, I found that when trying to find how to do it in bash. :-P –  derobert Aug 28 '12 at 18:09

It's not easy. The problem is that when you do:

rm -- *.txt


rm just sees the list of files, not the globbing pattern which has already been expanded by the shell.

What you could do is (zsh):

alias rm='noglob rm'


This tells zsh that patterns should not be expanded when calling rm. Then you can redefine rm as a function that does the expansion itself and adds the "-i" if need be something like:

'rm'() {
[[ "$*" = *[*[?]* ]] && set -- -i "$@"
command rm $~@ }  The problem with that approach though is that this new "rm" doesn't see the difference between rm *  and rm '*'  - Works in bash, probably in other shells. Place in your .bashrc function rm() { while test "${1:0:1}" = "-"; do
shift
done
if test $# -eq 1; then command rm "$1"
else
command rm -i "$@" fi }  - You can use command rm to avoid hard-coding PATH. Also, the approach of checking argument count is a bit unreliable, as rm can take options. – jw013 Aug 28 '12 at 18:44 The "$1" should be quoted, or this will fail if the single file passed contains a space. @jw013 - You can also escape the command, eg \rm –  jordanm Aug 28 '12 at 18:46
@jordanm You are correct about the need to quote \$1 with double quotes, but wrong about the command escaping. Quoting only suppresses aliases, NOT function look-up. This answer is suggesting a function, not an alias. –  jw013 Aug 28 '12 at 18:51
At least the old edit was functional - the new edit discards user command line options, which is probably not the correct thing to do. –  jw013 Aug 28 '12 at 18:54
@jw013 - I was not aware that only worked for alias lookups, not functions. Thanks for the information. –  jordanm Aug 28 '12 at 19:23