实时过滤 .bash/zsh_history 中误输入的无效命令,让历史记录更加简洁,便于查找
众所周知,在 Linux shell 中执行过的命令通常会被自动保存至当前用户目录下的 .bash_history / .zsh_history 等文件中,可以通过 history 命令查看。命令历史记录对于许多依赖历史命令进行分析和自动补全的 shell 插件是相当重要的。
实际使用过程中,手工键入的命令难免会出现错误,比如偶然打错了命令中的某个字母,导致 command not found。这部分错误的命令就成了命令历史记录中的“脏数据”。我们希望能有一种过滤机制,将这些无效命令从历史记录中剔除。
一种简洁高效的实现方案是:在任意一条命令执行完毕后,读取其返回值,判断命令是否有效(exit status 127 表示 command not found),若无效则将其从历史记录中删除。
我检索了互联网上的相关信息,中文社区内暂时不存在这方面的内容,英文社区内可以找到这样的一篇文章:Avoiding invalid commands in Bash history | boltblog,利用 bash 读取 PROMPT_COMMAND 环境变量的机制实现了上述功能。如果只使用 bash,只需照搬文中的命令放入 ~/.bashrc 中即可。
但是我发现,这个脚本对于 zsh 并不生效,一是因为 zsh 并不会在每个交互提示信息出现之前执行 ${PROMPT_COMMAND} 中的指令,而是提供了precmd 函数来实现类似的功能;二是 zsh 内建的 history 命令与 bash 有一定差异,比如它不支持通过 history -d 删除单条命令历史记录,而需要使用 fc 命令手动操作历史记录文件(参考 stackexchange)。
鉴于 ${ZSH_VERSION} (${BASH_VERSION}) 变量定义与否可以用于判断当前所处的 shell 类型,我将 bash 和 zsh 两种 shell 下实现无效命令历史记录过滤的方案整合为一段脚本:
1 | |
只需要将上面的代码放入 ~/.bashrc 或 ~/.zshrc 并重启 shell 即可生效。若上一步执行的命令 cmd 无效(not found),shell 将以红色字体提示 Deleted 'cmd' from history.。