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

107

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

echo "mysecret" > file

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

1  echo "mysecret" >| file
但是我如何轻松地从历史记录中删除一个条目呢? 在man zshbuiltins中我找不到对应的段落。

2
这个在StackOverflow上发帖,为什么不去SuperUser上发? - Charles Duffy
重复的内容 https://dev59.com/jmEh5IYBdhLWcg3wIgbN#63494728 的翻译。 - Marlon Richert
7个回答

129

*BSD/Darwin(macOS):

LC_ALL=C sed -i '' '/porn/d' $HISTFILE

Linux (GNU sed):

LC_ALL=C sed -i '/porn/d' $HISTFILE
这将从您的$HISTFILE中删除所有与“porn”匹配的行。
使用 `setopt HIST_IGNORE_SPACE`,您可以在上面的命令前加一个空格以防止它被写入$HISTFILE。
如下方评论中Tim指出,前缀LC_ALL=C可以防止“非法字节序列”错误。

3
注意,在OSX/BSD上,您需要在-i后面加上空引号来明确指定没有备份文件,因此:sed -i'' '/S3_SECRET/d' $HISTFILE。这在Linux上不起作用。https://dev59.com/n2025IYBdhLWcg3w960W - Tim Diggins
4
如果你遇到“illegal byte sequence”的错误,那么就将LC_ALL设置为C,如下所示:LC_ALL=C sed -i '' '/S3_SECRET/d' $HISTFILE。参考链接:https://dev59.com/iWgu5IYBdhLWcg3wfHE_ - Tim Diggins
2
不要忘记重新加载zsh,使用source .zshrc - MickGe

83

我不知道有没有一种优雅的方法来做这件事情,但在类似的情况下,我通常会退出(让zsh清空其缓冲区并将我的历史记录写入文件),然后登录,并 手动编辑 ~/.zsh_history 文件,删除“危险”的行。


3
对我有用。 我确实需要重新启动终端才能使更改生效。 - Dennis Hackethal
3
为了获得额外的分数,可以通过设置环境变量HISTFILE=/dev/null来避免加载历史文件,或者使用另一个shell。如果zsh是登录shell,则登录并执行sh,然后编辑~/.zhistory - gnucchi
它是有效的!从~/.zsh_history中删除命令,然后重新启动zsh。 - Ferris

45

如果您在zsh中使用HIST_IGNORE_SPACE选项,您可以在命令前面添加一个空格" ",这样它们就不会被记录在历史文件中。如果您有常用的秘密命令,您可以执行类似以下操作:alias hiddencommand=' hiddencommand'


注:HIST_IGNORE_SPACE是zsh中的一个选项,用于指示将命令行以空格开头的命令忽略掉,从而不会保存到历史记录文件中。以上内容涉及如何隐藏某些命令以避免在历史记录中出现。

10
请在您的 ~/.zshrc 文件中添加 setopt histignorespace。该命令的作用是忽略历史命令前的空格。 - Tim Abell
感谢使用 histignorespace。非常有用! - Matteo Gaggiano

11
如果你只是想偶尔删除一些命令,我认为手动编辑你的 .zsh_history 文件会更容易。
在 zsh 终端中:
  1. 使用要删除的命令关闭终端会话。
  2. 打开一个新的会话。
  3. 使用文本编辑器(如 pico、Emacs、vim 等)打开 ~/.zsh_history 文件。
  4. 删除有问题的行。
  5. 关闭编辑器,关闭终端会话并打开一个新的会话。
  6. 输入“history”命令,不需要的历史记录就会消失。
(请确保编辑器没有备份先前的 .zsh_history 实例。)
(解决方案基于 https://til.hashrocket.com/posts/zn87awopb4-delete-a-command-from-zsh-history-

8

这个函数可以从你的Zsh历史记录中删除任何一行,无需询问:

# 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."
}

如果您想要防止所有dc命令被写入历史记录,可以在您的~/.zshrc文件中添加以下内容:
zshaddhistory() {
 [[ $1 != 'dc '* ]]
}

更新

我现在已经发布了一个更全面的解决方案作为插件:https://github.com/marlonrichert/zsh-hist


4

简而言之:

vi $HISTFILE

更多细节:

运行 vi $HISTFILE

SHIFT + g — 跳到结尾

dd — 删除行

:wq — 保存并退出

重新加载会话或打开新标签页以查看更改


-4
BASH [不是 ZSH]中:
1- 在 bash 终端中输入 history # 这将列出 .bash_history 文件中所有命令及其行号
例如:
  ...
  987  cd
  988  ssh x@127.0.0.1
  990  exit
  991  cd

2- 选择您想要删除的CMD行号

history -d 988

注意:如果您想要删除最后3个CMD,只需从底部选择第三行编号,例如:988,并连续重复3次CMD history -d 988

来源


5
在ZSH中,"history -d"不能正常工作,因为它只是"fc -l 1"的别名,并且会出现"fc: event not found: -d"错误。为了避免这个问题,可以直接使用"fc -l 1"来代替"history -d"。 - Wirone
是的,我用Bash写的!以防有人需要Bash而不是Zsh。 - KhogaEslam

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接