1

Upon accidentally running the wrong command because of an incomplete Ctrl-R search and rm -rfing a file I needed, it got me thinking.

Is there a way to sanitise rm -rf foo to be saved in bash history as rm -r foo?
This will ensure if the command is accidentally run in the future, it will ask before doing so.
My rm is aliased to rm -iv, so I think this stops rm -r from removing without asking (I admit I have not run rm -r without the -i flag)

The reason I think this is possible is based on the bash bang builtins.

mkdir foo
cd !$

Will show in bash history:

mkdir foo
cd foo

Edit: while I appreciate the "don't save in history at all" solutions, I am aware of it and specifically wanted a different solution, as @tripleee explained.

Trav Easton
  • 401
  • 2
  • 6
  • 17
  • 1
    See also: http://unix.stackexchange.com/questions/32460/excluding-some-of-the-commands-from-being-getting-stored-in-bash-history – codeforester Mar 03 '17 at 03:36
  • Possible duplicate of [How to prevent commands to show up in bash history?](http://stackoverflow.com/questions/6475524/how-to-prevent-commands-to-show-up-in-bash-history) – codeforester Mar 03 '17 at 03:39
  • With your alias, `rm -rf` expands to `rm -iv -rf`, so the `-f` overrides the preceding `-i`. – chepner Mar 03 '17 at 03:48
  • 1
    While the nominated dupicate is probably the only sane answer (i.e. basically "don't do that") it doesn't directly answer the OP's question. I interpret this to mean "is there a facility to somehow filter what ends up in the history" (the answer to which is no, though Chepner's answer intriguingly offers a way to do roughly that) rather than "how do I completely remove some commands from the history" (which is a different thing, and easy to do). – tripleee Mar 03 '17 at 05:06

1 Answers1

4

I'm not sure how foolproof this is; it might miss some way of supplying the -f option. That said, you can override rm with the following:

rm () {
  local HISTIGNORE="$HISTIGNORE:command rm *"
  local arg process
  local -a sanitized
  command rm "$@"
  process=true
  for arg in "$@"; do
    if [[ $process && $arg = -*f* ]]; then
      sanitized+=("${arg//f/}")
    elif [[ $arg == -- ]]; then
      process=
    else
      sanitized+=("$arg")
    fi
  done
  history -s rm "${sanitized[@]}"
}

This works as follows:

  1. Temporarily add the pattern command rm * to the HISTIGNORE list, so that the command about to be executed isn't added to history.
  2. Execute the command as requested.
  3. Walk through the arguments, looking for any that contain the -f option. (Either standalone or in a cluster of short options.) Any such word should have the f removed. Sanitized words are added to a new array.
  4. The history -s command adds the reconstructed command (with sanitized arguments) to the history list.
chepner
  • 497,756
  • 71
  • 530
  • 681
  • This is a really interesting way to solve this. Because of my alias, this shows in history as `rm -iv -r foo` but it's still excellent. Re-running the command asks me before deleting anything. Thank you. – Trav Easton Mar 03 '17 at 08:47