tcsh,仅在命令成功时将命令保存在历史记录中

tcsh, save command in a history, only if the command was successful

我是 tcsh 的新手,请多多指教。现在我使用 postcmd 变量来保存历史:

alias postcmd "history -S; history -M;"

问题是,它几乎将我键入的所有内容都保存到终端。我想过滤掉一些拼写错误的命令,或者,例如,返回一些非零状态的命令。我的第一次尝试是这样的:

alias postcmd "if ($? == 0) history -S; history -M;"

但是上面,仍然保存了所有拼写错误的命令和非零退出状态的命令。 问题是,如何让tcsh过滤掉尽可能多的不合适的指令?

*更新*

我不知道如何让 tcsh 历史按照我想要的方式运行,所以我在这里给自己留个便条。我做的是

set history = 0

就是这样。

set savehist = (3000 merge lock)
alias precmd 'if($? == 0) history -S; history -c; history -M'

然后

tcsh% true
tcsh% false
tcsh% false
tcsh% true
tcsh% history
    20  0:15    true
    21  0:16    true
    22  0:16    history

为什么 history -c

清除历史;否则失败/拼写错误的命令仍将添加到当前(内存中)历史记录中,随后的 history -S 将保存它们,即使仅在成功命令后调用。

请注意,在 if(..) cmd1; cmd2; cmd3 中,cmd2cmd3 将无条件地 运行。

为什么 precmd 而不是 postcmd

tcsh% alias postcmd 'echo postcmd = $?'
tcsh% alias precmd 'echo precmd = $?'
postcmd = 0
precmd = 0
tcsh% false
postcmd = 0
precmd = 1

中间别名是否可以对命令进行分组?

不行,因为if (...)后面的命令不能是别名:

tcsh% alias ok 'echo ok'
tcsh% ok
ok
tcsh% if (1) ok
ok: Command not found.

来自 tcsh(1) 联机帮助页:

if (expr) command

... command must be a simple command, not an alias, a pipeline, a command list or a parenthesized command list, but it may have arguments

为什么不使用 precmdpostcmd 的多行别名?

因为它会递归调用自己:

tcsh% alias postcmd 'if ($? == 0) then\
echo OK\
endif\
'
OK
OK
<ad nauseam>
^C