管理你的 Shell 历史记录
Curate your shell history

原始链接: https://esham.io/2025/05/shell-history

Simon Tatham 提倡禁用 shell 历史文件,偏好“短暂性策略”。他认为保存每个命令,包括错别字和失败尝试,会污染历史记录,导致意外调用错误命令。相反,他将有用的命令保存为 shell 函数、脚本或笔记。 作者虽然不同意完全禁用历史记录,选择了一种最大化的方法,但也承认历史文件中存在“杂草”的问题。他开发了一个名为“smite”的 Zsh 函数来选择性地删除不需要的条目。 “smite” 使用 `fzf` 提供一个交互式的 shell 历史浏览器,允许用户选择和删除命令。默认情况下,它只显示当前会话的历史记录,但可以使用 `-a` 标志显示整个历史记录。然后,选定的命令将从历史文件中删除。作者发现这种选择性修剪比盲目保存每个命令更有用。

Hacker News 的讨论围绕着 shell 历史记录的管理策略展开。原文建议整理收集有用的 shell 脚本,而不是仅仅依赖命令历史记录。一些评论者强烈反对这种观点,他们主张保留全面、带时间戳,甚至跨机器同步的历史记录,以便使用 `grep` 或 Atuin 等专用工具轻松回忆过去的命令。 许多用户发现全面的历史记录(包括错误)具有极大的价值,这有助于故障排除、技术入门以及重建过去的流程。他们认为整理会增加不必要的开销。另一些人则专注于减少历史记录中噪音的技术,例如忽略某些命令或使用工具删除成功的命令。 讨论涉及大型历史文件可能造成的性能影响以及异步加载和特定目录历史记录等可能的优化方法。一些人发现整理本身很有价值,它能帮助他们反思并改进工作流程。替代方法包括完全禁用 shell 历史记录,以及依赖浏览器中的软书签。甚至有人提出使用 LLM 驱动的历史记录搜索,尽管也有人担心速度问题。

原文

Simon Tatham wrote an article recently called “Policy of transience”, explaining (among other things) why you might want to disable your shell history file. Simon writes:

My unusual habit is: turn off the history file completely, by putting the command ‘unset HISTFILE’ in my .bashrc. I still get history within a single instance of the shell, so I can edit my last command ten times until it works properly; but history isn’t shared between my terminal windows, or preserved when I log out and log in again. All the shell history I allow myself is localised and short-term.

[…]

If I type a shell command that’s valuable – one that did something useful enough that I might want it again in future, and long and complicated enough that I’d be annoyed to have to figure it out a second time from scratch – then I can’t rely on it just happening to be in my .bash_history. So instead I put it somewhere else: maybe a shell function in my .bashrc, or maybe a shell script in my directory of random useful scriptlets. Or maybe just in a file of notes jotted down to myself about useful shell runes to remember.

I find this a more useful way to remember shell commands. Firstly, this procedure separates the working version of the command from all the failed attempts just before it. Even within the context of one instance of bash I’ll sometimes accidentally recall a wrong version of a command when I was aiming for the corrected one two commands later; the idea of having a year’s worth of my own false starts available for accidental recall seems horrifying! Instead, I deliberately save just the working version, and let all the failed attempts go in the trash when I close the shell.

For me, this idea feels uncomfortable! If anything, I’m a shell history maximalist; I have zsh configured to save my last 9,800 commands. I rely heavily on my shell history to remember how I did things before. I suspect my most-used form of zsh completion is to complete the current command line from a history entry.

But I also think Simon makes a good point about how useless it is to record all of your false starts. Why save cd ~/Dekstop, which I’m never going to want to run again? Why save vim /etc/rc.conf when sudo vim /etc/rc.conf is what I meant 100% of the time? At best, these dead-end commands are taking up unnecessary space in my history file. At worst, they’ll trip me up again the next time I need to do the same thing and naively run the first command from my history that looks right.


For myself, I don’t want my shell history to be opt-in. But I can make it easier to remove the typos and dead ends. I came up with this zsh function to facilitate that:

fzf-powered browser with your shell history in it. (So you’ll need fzf installed, but that’s the only dependency.) By default, you’ll only see your history from the current session, but running smite -a shows all of your history.

When you navigate to an entry and press Return or Enter, zsh will delete all instances of that command from your history. If you want to delete multiple commands at once, you can select them by pressing Tab on each one and then typing Return to commit your changes.

Multiline commands are not handled correctly, for now.

The function prints back all of the commands it’s deleting, just in case you select the wrong one.

Here’s a video:

The approach is taken from this Stack Overflow answer by Marlon Richert, who later wrote a zsh plugin called zsh-hist to make the history system easier to deal with. (I haven’t tried the plugin, but it seems to make it possible to delete the history entry with a given number, which is the omission in zsh that prevents multi-line commands from being easy to delete.)


Even if my zsh code isn’t relevant to you, I hope you’ve taken a moment to consider what you want out of your shell history and if there’s anything you could tweak to get closer to that.

Since adding this function to my zshrc, I’ve been paying more attention to which commands are misfires, and pruning the ones that are. If my history file is never quite going to be a beautiful garden, I can at least put more effort into removing the weeds.

联系我们 contact @ memedata.com