如何从 ZSH 的历史记录中删除条目

假设我使用 zsh 运行了一个命令

echo "mysecret" > file

我可以使用命令 fc -l轻松地打印包括条目编号在内的历史记录:

1  echo "mysecret" >| file

但是如何轻松地从历史记录中删除条目呢?

我在 Man zshbuiltins中找不到相应的段落。

50332 次浏览

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.

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'.

*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.

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 x@127.0.0.1
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.

Source

This function will remove any one line you want from your Zsh history, no questions asked:

# Accepts one history line number as argument.
# Use `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

If you only want to make an occasional deletion, I think that it's easier to manually edit your .zshell_history.

In a zsh terminal:

  1. Close the terminal session with the command to delete.
  2. open a new session,
  3. open ~/.zsh_history with a text editor (pico, Emacs, vim...),
  4. delete the faulty lines,
  5. close the editor, close the terminal session and open a new one,
  6. enter history and the unwanted history item will be gone.

(Make sure the editor hasn't backed up the previous .zsh_history instance.)

(Solution based on https://til.hashrocket.com/posts/zn87awopb4-delete-a-command-from-zsh-history-)