How to remove an entry from the history in ZSH
ZshZsh Problem Overview
Let's say I ran a command using a zsh
echo "mysecret" > file
I can easily print the history including the entry numbers using the command fc -l
:
> 1 echo "mysecret" >| file
But how can I easily delete an entry from the history?
I cannot find a corresponding paragraph in man zshbuiltins.
Zsh Solutions
Solution 1 - Zsh
*BSD/Darwin (macOS):
LC_ALL=C sed -i '' '/porn/d' $HISTFILE
Linux (GNU sed):
LC_ALL=C sed -i '/porn/d' $HISTFILE
This will remove all lines matching "porn" from your $HISTFILE.
With setopt HIST_IGNORE_SPACE
, you can prepend the above command with a space character to prevent it from being written to $HISTFILE.
As Tim pointed out in his comment below, the prefix LC_ALL=C prevents 'illegal byte sequence' failure.
Solution 2 - Zsh
I don't know if there is some elegant method for doing this, but in similar situations I have logged out (allowing zsh to empty its buffer and write my history to file), then logged in, and finally manually edited ~/.zsh_history
, deleting the "dangerous" line.
Solution 3 - Zsh
If you use the HIST_IGNORE_SPACE option in zsh you can prepend commands with a space " " and they will not be remembered in the history file. If you have secret commands you commonly use you can do something along the lines of: alias hiddencommand=' hiddencommand'.
Solution 4 - Zsh
I think the solution I found is easier.
In a zsh terminal (in mac os)
- I closed the terminal session in which I had a command I wanted to delete.
- Opened a new session,
- opened ~/.zsh_history with a text editor (I used emacs but nano or any other would do, I guess),
- deleted the faulty lines, closed the editor,
- closed the Terminal session,
- opened a new Terminal sessionsession,
- entered
history
and the unwanted history item was gone.
Make sure emacs hasn't backed up the previous .zsh_history instance.
(Solution based on https://til.hashrocket.com/posts/zn87awopb4-delete-a-command-from-zsh-history-)
Solution 5 - Zsh
This function will remove any one line you want from your Zsh history, no questions asked:
# Accepts one history line number as argument.
# Alternatively, you can do `dc -1` to remove the last line.
dc () {
# Prevent the specified history line from being saved.
local HISTORY_IGNORE="${(b)$(fc -ln $1 $1)}"
# Write out the history to file, excluding lines that match `$HISTORY_IGNORE`.
fc -W
# Dispose of the current history and read the new history from file.
fc -p $HISTFILE $HISTSIZE $SAVEHIST
# TA-DA!
print "Deleted '$HISTORY_IGNORE' from history."
}
If you want to additionally prevent all dc
commands from being written to history, add the following in your ~/.zshrc
file:
zshaddhistory() {
[[ $1 != 'dc '* ]]
}
Update
I've now published a more comprehensive solution as a plugin: https://github.com/marlonrichert/zsh-hist
Solution 6 - Zsh
In BASH [Not ZSH]:
1- in bash terminal type
hsitory
# This will list all commands in history .bash_history file with line numbers
ex:
...
987 cd
988 ssh [email protected]
990 exit
991 cd
2- pick the CMD line number you want to delete
history -d 988
Note: if you want to delete for example last 3 CMDs, just pick the third line number from bottom ex: 988 and repeat the CMD history -d 988
3 times in sequence.