我通常使用zsh,它提供了chpwd()钩子函数。也就是说:如果cd内置命令改变了当前工作目录(cwd),那么如果存在chpwd()方法,zsh会自动调用它。这允许设置依赖于cwd的变量和别名。
现在我想将我的.zshrc中的这部分内容移植到bash,但发现bash不认识chpwd()。在bash中是否已经有类似的功能?我知道重新定义cd可以解决问题(见下文),但我希望获得更优雅的解决方案。
function cd()
{
builtin cd $@
chpwd
}
trap chpwd DEBUG # calls the function before each command
PROMPT_COMMAND=chpwd # calls the function after each command
请注意,PROMPT_COMMAND
中定义的函数在每个提示符之前都会运行,即使是空提示符。
DEBUG
陷阱在每个简单命令之前执行,这意味着:(a)如果您的命令行是一个列表-例如,:; :
,则陷阱命令对该列表中的每个命令都会执行;(b)如果您还设置了$PROMPT_COMMAND
,那么在那里定义的命令也会触发陷阱。 - mklement0$PROMPT_COMMAND
可能已经以 ;
结尾,可能带有尾随空格(实际上,OSX 就是这样做的: "update_terminal_cwd; "
);如果您盲目地在该事件中追加 ;
,将导致两个连续的 ;
,从而引起语法错误。我的命令可以防止这种情况发生。 - mklement0PROMPT_COMMAND=chpwd
或其变体的好处与zsh相比是,当终端刚打开时,zsh上的chpwd钩子不会触发,但PROMPT_COMMAND会触发。 - Thomchpwd
钩子。
与其他现代shell相比,Bash没有完整的钩子系统设计。在Bash中,PROMPT_COMMAND
变量被用作钩子函数,它相当于ZSH中的precmd
钩子、Fish中的fish_prompt
。目前为止,我所知道的唯一拥有内置chpwd
钩子的shell是ZSH。
PROMPT_COMMAND
如果设置了该变量,它将被解释为每个主提示符($PS1)打印之前要执行的命令。
https://www.gnu.org/savannah-checkouts/gnu/bash/manual/bash.html#Bash-Variables
chpwd
钩子PROMPT_COMMAND
设置一个等效于chpwd
的钩子。# create a PROPMT_COMMAND equivalent to store chpwd functions
typeset -g CHPWD_COMMAND=""
_chpwd_hook() {
shopt -s nullglob
local f
# run commands in CHPWD_COMMAND variable on dir change
if [[ "$PREVPWD" != "$PWD" ]]; then
local IFS=$';'
for f in $CHPWD_COMMAND; do
"$f"
done
unset IFS
fi
# refresh last working dir record
export PREVPWD="$PWD"
}
# add `;` after _chpwd_hook if PROMPT_COMMAND is not empty
PROMPT_COMMAND="_chpwd_hook${PROMPT_COMMAND:+;$PROMPT_COMMAND}"
# example 1: `ls` list directory once dir is changed
_ls_on_cwd_change() {
ls
}
# append the command into CHPWD_COMMAND
CHPWD_COMMAND="${CHPWD_COMMAND:+$CHPWD_COMMAND;}_ls_on_cwd_change"
# or just use `ls` directly
CHPWD_COMMAND="${CHPWD_COMMAND:+$CHPWD_COMMAND;}ls"
cd
函数不够优雅? - user123444555621function cd
并不优雅,因为它仅处理cd
。如果您使用pushd
或popd
更改目录,则还必须将它们包装起来。这并不是无法克服的障碍,但使用zsh
的chpwd
钩子意味着您只需定义该钩子,而无需详尽地确定工作目录可能发生的所有可能方式,同时仍然不需要像PROMPT_COMMAND
那样每次显示提示符时运行(可能昂贵的)代码。 - ShadowRanger