Skip to main content
added 9 characters in body
Source Link
Stéphane Chazelas
  • 586.9k
  • 96
  • 1.1k
  • 1.7k

You could do something like:

fixhist() {
   local cmd histnum
   cmd=$(HISTTIMEFORMAT=/ history 1)
   histnum=$((${cmd%%cmd%%[*/*]*}))
   cmd=${cmd#*/} # remove the histnum
   case $cmd in
     (rm\ *|mv\ *|...)
       history -d "$histnum" # delete
       history -s "#$cmd"    # add back with a #
   esac
}
PROMPT_COMMAND=fixhist

The idea being that before each prompt, we check the last history entry (history 1) and if it's one of the dangerous ones, we delete it (history -d) and add it back with a # with history -s.

(obviously, you need to remove your HISTIGNORE setting).

An unwanted side effect of that though is that it alters the history time of those rm, mv... commands.

To fix that, an alternative could be:

fixhist() {
   local cmd time histnum
   cmd=$(HISTTIMEFORMAT='<%s>' history 1)
   histnum=$((${cmd%%<*cmd%%[<*]*}))
   time=${cmd%%>*}
   time=${time#*<}
   cmd=${cmd#*>}
   case $cmd in
     (rm\ *|mv\ *|...)
       history -d "$histnum" # delete
       HISTFILE=/dev/stdin history -r <<EOF
#$time
#$cmd
EOF
   esac
}
PROMPT_COMMAND=fixhist

This time, we record the time of the last history, and to add back the history line, we use history -r from a temporary file (the here document) that includes the timestamp.

You'd want the fixhist to be performed before your history -a; history -c; history -r. Unfortunately, the current version of bash has a bug in that history -a doesn't save that extra line that we've added. A work around is to write it instead:

fixhist() {
   local cmd time histnum
   cmd=$(HISTTIMEFORMAT='<%s>' history 1)
   histnum=$((${cmd%%<*cmd%%[<*]*}))
   time=${cmd%%>*}
   time=${time#*<}
   cmd=${cmd#*>}
   case $cmd in
     (rm\ *|mv\ *|...)
       history -d "$histnum" # delete
       history -a
       [ -f "$HISTFILE" ] && printf '#%s\n' "$time" "$cmd" >> "$HISTFILE";;
     (*)
       history -a
   esac
   history -c
   history -r
}
PROMPT_COMMAND=fixhist

That is to append the commented command to the HISTFILE ourselves instead of letting history -a do it.

You could do something like:

fixhist() {
   local cmd histnum
   cmd=$(HISTTIMEFORMAT=/ history 1)
   histnum=$((${cmd%%/*}))
   cmd=${cmd#*/} # remove the histnum
   case $cmd in
     (rm\ *|mv\ *|...)
       history -d "$histnum" # delete
       history -s "#$cmd"    # add back with a #
   esac
}
PROMPT_COMMAND=fixhist

The idea being that before each prompt, we check the last history entry (history 1) and if it's one of the dangerous ones, we delete it (history -d) and add it back with a # with history -s.

(obviously, you need to remove your HISTIGNORE setting).

An unwanted side effect of that though is that it alters the history time of those rm, mv... commands.

To fix that, an alternative could be:

fixhist() {
   local cmd time histnum
   cmd=$(HISTTIMEFORMAT='<%s>' history 1)
   histnum=$((${cmd%%<*}))
   time=${cmd%%>*}
   time=${time#*<}
   cmd=${cmd#*>}
   case $cmd in
     (rm\ *|mv\ *|...)
       history -d "$histnum" # delete
       HISTFILE=/dev/stdin history -r <<EOF
#$time
#$cmd
EOF
   esac
}
PROMPT_COMMAND=fixhist

This time, we record the time of the last history, and to add back the history line, we use history -r from a temporary file (the here document) that includes the timestamp.

You'd want the fixhist to be performed before your history -a; history -c; history -r. Unfortunately, the current version of bash has a bug in that history -a doesn't save that extra line that we've added. A work around is to write it instead:

fixhist() {
   local cmd time histnum
   cmd=$(HISTTIMEFORMAT='<%s>' history 1)
   histnum=$((${cmd%%<*}))
   time=${cmd%%>*}
   time=${time#*<}
   cmd=${cmd#*>}
   case $cmd in
     (rm\ *|mv\ *|...)
       history -d "$histnum" # delete
       history -a
       [ -f "$HISTFILE" ] && printf '#%s\n' "$time" "$cmd" >> "$HISTFILE";;
     (*)
       history -a
   esac
   history -c
   history -r
}
PROMPT_COMMAND=fixhist

That is to append the commented command to the HISTFILE ourselves instead of letting history -a do it.

You could do something like:

fixhist() {
   local cmd histnum
   cmd=$(HISTTIMEFORMAT=/ history 1)
   histnum=$((${cmd%%[*/]*}))
   cmd=${cmd#*/} # remove the histnum
   case $cmd in
     (rm\ *|mv\ *|...)
       history -d "$histnum" # delete
       history -s "#$cmd"    # add back with a #
   esac
}
PROMPT_COMMAND=fixhist

The idea being that before each prompt, we check the last history entry (history 1) and if it's one of the dangerous ones, we delete it (history -d) and add it back with a # with history -s.

(obviously, you need to remove your HISTIGNORE setting).

An unwanted side effect of that though is that it alters the history time of those rm, mv... commands.

To fix that, an alternative could be:

fixhist() {
   local cmd time histnum
   cmd=$(HISTTIMEFORMAT='<%s>' history 1)
   histnum=$((${cmd%%[<*]*}))
   time=${cmd%%>*}
   time=${time#*<}
   cmd=${cmd#*>}
   case $cmd in
     (rm\ *|mv\ *|...)
       history -d "$histnum" # delete
       HISTFILE=/dev/stdin history -r <<EOF
#$time
#$cmd
EOF
   esac
}
PROMPT_COMMAND=fixhist

This time, we record the time of the last history, and to add back the history line, we use history -r from a temporary file (the here document) that includes the timestamp.

You'd want the fixhist to be performed before your history -a; history -c; history -r. Unfortunately, the current version of bash has a bug in that history -a doesn't save that extra line that we've added. A work around is to write it instead:

fixhist() {
   local cmd time histnum
   cmd=$(HISTTIMEFORMAT='<%s>' history 1)
   histnum=$((${cmd%%[<*]*}))
   time=${cmd%%>*}
   time=${time#*<}
   cmd=${cmd#*>}
   case $cmd in
     (rm\ *|mv\ *|...)
       history -d "$histnum" # delete
       history -a
       [ -f "$HISTFILE" ] && printf '#%s\n' "$time" "$cmd" >> "$HISTFILE";;
     (*)
       history -a
   esac
   history -c
   history -r
}
PROMPT_COMMAND=fixhist

That is to append the commented command to the HISTFILE ourselves instead of letting history -a do it.

Bounty Awarded with 100 reputation awarded by Martin Vegter
added 693 characters in body
Source Link
Stéphane Chazelas
  • 586.9k
  • 96
  • 1.1k
  • 1.7k

You'd want the fixhist to be performed before your history -a; history -c; history -r. So:

PROMPT_COMMAND='
  fixhist
  history -a
  history -c
  history -r'

An unwanted side effect of that though is that it alters the history time of those rm, mv... commands.

This time, we record the time of the last history, and to add back the history line, we use history -r from a temporary file (the here document) that includes the timestamp.

You'd want the fixhist to be performed before your history -a; history -c; history -r. Unfortunately, the current version of bash has a bug in that history -a doesn't save that extra line that we've added. A work around is to write it instead:

fixhist() {
   local cmd time histnum
   cmd=$(HISTTIMEFORMAT='<%s>' history 1)
   histnum=$((${cmd%%<*}))
   time=${cmd%%>*}
   time=${time#*<}
   cmd=${cmd#*>}
   case $cmd in
     (rm\ *|mv\ *|...)
       history -d "$histnum" # delete
       history -a
       [ -f "$HISTFILE" ] && printf '#%s\n' "$time" "$cmd" >> "$HISTFILE";;
     (*)
       history -a
   esac
   history -c
   history -r
}
PROMPT_COMMAND=fixhist

That is to append the commented command to the HISTFILE ourselves instead of letting history -a do it.

You'd want the fixhist to be performed before your history -a; history -c; history -r. So:

PROMPT_COMMAND='
  fixhist
  history -a
  history -c
  history -r'

An unwanted side effect of that though is that it alters the history time of those rm, mv... commands.

This time, we record the time of the last history, and to add back the history line, we use history -r from a temporary file (the here document) that includes the timestamp.

An unwanted side effect of that though is that it alters the history time of those rm, mv... commands.

This time, we record the time of the last history, and to add back the history line, we use history -r from a temporary file (the here document) that includes the timestamp.

You'd want the fixhist to be performed before your history -a; history -c; history -r. Unfortunately, the current version of bash has a bug in that history -a doesn't save that extra line that we've added. A work around is to write it instead:

fixhist() {
   local cmd time histnum
   cmd=$(HISTTIMEFORMAT='<%s>' history 1)
   histnum=$((${cmd%%<*}))
   time=${cmd%%>*}
   time=${time#*<}
   cmd=${cmd#*>}
   case $cmd in
     (rm\ *|mv\ *|...)
       history -d "$histnum" # delete
       history -a
       [ -f "$HISTFILE" ] && printf '#%s\n' "$time" "$cmd" >> "$HISTFILE";;
     (*)
       history -a
   esac
   history -c
   history -r
}
PROMPT_COMMAND=fixhist

That is to append the commented command to the HISTFILE ourselves instead of letting history -a do it.

added 62 characters in body
Source Link
Stéphane Chazelas
  • 586.9k
  • 96
  • 1.1k
  • 1.7k

You could do something like:

fixhist() {
   local cmd histnum
   cmd=$(HISTTIMEFORMAT=/ history 1)
   histnum=$((${cmd%%/*}))
   cmd=${cmd#*/} # remove the histnum
   case $cmd in
     (rm\ *|mv\ *|...)
       history -d "$histnum" # delete
       history -s "#$cmd"    # add back with a #
   esac
}
PROMPT_COMMAND=fixhist

The idea being that before each prompt, we check the last history entry (history 1) and if it's one of the dangerous ones, we delete it (history -d) and add it back with a # with history -s.

(obviously, you need to remove your HISTIGNORE setting).

You'd want the fixhist to be performed before your history -a; history -c; history -r. So:

PROMPT_COMMAND='
  fixhist
  history -a
  history -c
  history -r'

An unwanted side effect of that though is that it alters the history time of those rm, mv... commands.

To fix that, an alternative could be:

fixhist() {
   local cmd time histnum
   cmd=$(HISTTIMEFORMAT='<%s>' history 1)
   histnum=$((${cmd%%<*}))
   time=${cmd%%>*}
   time=${time#*<}
   cmd=${cmd#*>}
   case $cmd in
     (rm\ *|mv\ *|...)
       history -d "$histnum" # delete
       HISTFILE=/dev/stdin history -r <<EOF
#$time
#$cmd
EOF
   esac
}
PROMPT_COMMAND=fixhist

This time, we record the time of the last history, and to add back the history line, we use history -r from a temporary file (the here document) that includes the timestamp.

You could do something like:

fixhist() {
   local cmd histnum
   cmd=$(HISTTIMEFORMAT=/ history 1)
   histnum=$((${cmd%%/*}))
   cmd=${cmd#*/} # remove the histnum
   case $cmd in
     (rm\ *|mv\ *|...)
       history -d "$histnum" # delete
       history -s "#$cmd"    # add back with a #
   esac
}
PROMPT_COMMAND=fixhist

The idea being that before each prompt, we check the last history entry (history 1) and if it's one of the dangerous ones, we delete it (history -d) and add it back with a # with history -s.

You'd want the fixhist to be performed before your history -a; history -c; history -r. So:

PROMPT_COMMAND='
  fixhist
  history -a
  history -c
  history -r'

An unwanted side effect of that though is that it alters the history time of those rm, mv... commands.

To fix that, an alternative could be:

fixhist() {
   local cmd time histnum
   cmd=$(HISTTIMEFORMAT='<%s>' history 1)
   histnum=$((${cmd%%<*}))
   time=${cmd%%>*}
   time=${time#*<}
   cmd=${cmd#*>}
   case $cmd in
     (rm\ *|mv\ *|...)
       history -d "$histnum" # delete
       HISTFILE=/dev/stdin history -r <<EOF
#$time
#$cmd
EOF
   esac
}
PROMPT_COMMAND=fixhist

This time, we record the time of the last history, and to add back the history line, we use history -r from a temporary file (the here document) that includes the timestamp.

You could do something like:

fixhist() {
   local cmd histnum
   cmd=$(HISTTIMEFORMAT=/ history 1)
   histnum=$((${cmd%%/*}))
   cmd=${cmd#*/} # remove the histnum
   case $cmd in
     (rm\ *|mv\ *|...)
       history -d "$histnum" # delete
       history -s "#$cmd"    # add back with a #
   esac
}
PROMPT_COMMAND=fixhist

The idea being that before each prompt, we check the last history entry (history 1) and if it's one of the dangerous ones, we delete it (history -d) and add it back with a # with history -s.

(obviously, you need to remove your HISTIGNORE setting).

You'd want the fixhist to be performed before your history -a; history -c; history -r. So:

PROMPT_COMMAND='
  fixhist
  history -a
  history -c
  history -r'

An unwanted side effect of that though is that it alters the history time of those rm, mv... commands.

To fix that, an alternative could be:

fixhist() {
   local cmd time histnum
   cmd=$(HISTTIMEFORMAT='<%s>' history 1)
   histnum=$((${cmd%%<*}))
   time=${cmd%%>*}
   time=${time#*<}
   cmd=${cmd#*>}
   case $cmd in
     (rm\ *|mv\ *|...)
       history -d "$histnum" # delete
       HISTFILE=/dev/stdin history -r <<EOF
#$time
#$cmd
EOF
   esac
}
PROMPT_COMMAND=fixhist

This time, we record the time of the last history, and to add back the history line, we use history -r from a temporary file (the here document) that includes the timestamp.

added 105 characters in body
Source Link
Stéphane Chazelas
  • 586.9k
  • 96
  • 1.1k
  • 1.7k
Loading
added 105 characters in body
Source Link
Stéphane Chazelas
  • 586.9k
  • 96
  • 1.1k
  • 1.7k
Loading
added 105 characters in body
Source Link
Stéphane Chazelas
  • 586.9k
  • 96
  • 1.1k
  • 1.7k
Loading
added 245 characters in body
Source Link
Stéphane Chazelas
  • 586.9k
  • 96
  • 1.1k
  • 1.7k
Loading
Source Link
Stéphane Chazelas
  • 586.9k
  • 96
  • 1.1k
  • 1.7k
Loading