在 $PWD 发生任何更改后,如何在 bash 中运行命令?

Nat*_*ong 12 bash hook pwd

zsh 提供了一些不错的钩子函数,包括chpwd在用户更改目录后运行函数。

# zsh only
function greet() { echo 'hi'; }
chpwd_functions+=("greet")
cd .. # hi
pushd # hi
popd  # hi
Run Code Online (Sandbox Code Playgroud)

我正在尝试在 bash 中模拟它。

约束:

  • 它必须在交互式和非交互式 shell 中都可以工作,我认为这意味着它不能依赖于类似的东西 $PROMPT_COMMAND
  • 它不能重新定义cd,因为我希望它适用于任何更改目录的命令(例如,pushdpopd
  • 它必须用户的命令之后运行,所以trap "my_function" DEBUG不起作用,除非我能以某种方式在那里说,“首先运行$BASH_COMMAND我们被困,然后也这样做......”我看到我可以避免启用$BASH_COMMAND if 的自动运行并且trap 函数返回 1,但我认为我不想强制,并且返回成功(但已修改)的命令似乎是错误的。extdebugextdebug1

最后一部分——“按照用户的命令运行”——是目前让我感到困惑的部分。如果我可以在每个命令之后运行一个函数,我可以让它检查自上次检查以来目录是否已更改。例如:

function check_pwd() {
  # true in a new shell (empty var) or after cd
  if [ "$LAST_CHECKED_DIR" != "$PWD" ]; then
    my_function
  fi
  LAST_CHECKED_DIR=$PWD
}
Run Code Online (Sandbox Code Playgroud)

我是在正确的轨道上,还是有更好的方法?用户更改目录后,如何在 bash 中运行命令?

Gre*_*gor 2

如果维护者不喜欢您更改 cd 的定义,另一个选择是重新定义使用此目录内环境的所有命令:

for c in cmd1 cmd2 cmd3 cmd4 cmd5 ; do
    eval "$c() { check_pwd ; command $c \"\$@\" ; }"
done
Run Code Online (Sandbox Code Playgroud)

这将非常有效,因为 PWD 挂钩和目录内配置仅在需要时才会被处理。

在您的示例 check_pwd 函数中,我可能会更改:

my_function
Run Code Online (Sandbox Code Playgroud)

到:

my_function "$PWD"
Run Code Online (Sandbox Code Playgroud)

为了传递新的cwd(可能更加模块化,可测试)。