cho*_*ger 6 shell command zsh resolution path
我在这里尝试使用一个非常基本的设置模式:我有两个不同的给定工具安装(ocamlc,但这并不重要)。为了选择一个工具,我尝试通过添加一个条目来覆盖 PATH 变量。
% where ocamlc
/home/choeger/ueb/uebb/amsun-integration/Runtime/test_src/../../opam/4.02.3/bin/ocamlc
/home/choeger/.opam/4.02.3/bin/ocamlc
/usr/bin/ocamlc
Run Code Online (Sandbox Code Playgroud)
但是,zsh 仍然使用旧条目:
% ocamlc -v
The OCaml compiler, version 4.02.3
Standard library directory: /home/choeger/.opam/4.02.3/lib/ocaml
Run Code Online (Sandbox Code Playgroud)
(可以看到它使用了第二个条目,因为库目录是硬编码到该安装的)
Bash 的行为符合预期:
% bash -c "ocamlc -v"
The OCaml compiler, version 4.02.3
Standard library directory: /home/choeger/ueb/uebb/amsun-integration/opam/4.02.3/lib/ocaml
Run Code Online (Sandbox Code Playgroud)
那么为什么 zsh 忽略第一个 PATH 条目,尽管它将它列为的第一个元素where
?
编辑:为了验证 zsh 没有调用相同的二进制文件,这里是另一个运行:
% type -a ocamlc
ocamlc is /home/choeger/ueb/uebb/amsun-integration/tests/pendulum/../../opam/4.02.3/bin/ocamlc
ocamlc is /home/choeger/.opam/4.02.3/bin/ocamlc
ocamlc is /usr/bin/ocamlc
% ocamlc -v
The OCaml compiler, version 4.02.3
Standard library directory: /home/choeger/.opam/4.02.3/lib/ocaml
% /home/choeger/ueb/uebb/amsun-integration/tests/pendulum/../../opam/4.02.3/bin/ocamlc -v
The OCaml compiler, version 4.02.3
Standard library directory: /home/choeger/ueb/uebb/amsun-integration/opam/4.02.3/lib/ocaml
Run Code Online (Sandbox Code Playgroud)
edit2:这是 setopt 输出:
% setopt
autocd
autopushd
nobeep
completeinword
correct
extendedglob
extendedhistory
histignorealldups
histignorespace
nohup
interactive
interactivecomments
longlistjobs
monitor
nonomatch
pushdignoredups
shinstdin
zle
%
Run Code Online (Sandbox Code Playgroud)
Config 是此处找到的 grml 配置以及 .local 文件中的一些路径变量。
默认情况下zsh
,第一次执行命令时会散列命令的位置。第二次执行时,使用散列路径。刷新哈希表运行
rehash
Run Code Online (Sandbox Code Playgroud)
或者
hash -r
Run Code Online (Sandbox Code Playgroud)
每次更改时都会自动发生这种情况PATH
,其主要用途是将新的可执行文件添加到PATH
.
注意:对于特定用例,以下内容可能有点矫枉过正。但它也确实解决了这个问题,并且可能对稍微不同的用例感兴趣。
如果您不关心(可能可以忽略不计)性能影响,您可以通过禁用该HASH_CMDS
选项来禁用命令散列:
setopt nohashcmds
Run Code Online (Sandbox Code Playgroud)
虽然zsh
仍将使用哈希表,但它不会自动添加每个命令。因此,除非通过其他方式zsh
将命令输入到哈希表中,否则PATH
每次都会检查该命令。
如果CORRECT
设置了该选项,这可能仍会导致问题。由于这确实设置了哈希表以提供拼写更正,但在PATH
更改时不一定会刷新它。为了自动刷新表格,您可以使用precmd
每次打印提示之前执行的钩子。
autoload -Uz add-zsh-hook
auto_rehash () {
rehash
}
add-zsh-hook precmd auto_rehash
Run Code Online (Sandbox Code Playgroud)
zsh 不会跳过 PATH 条目。但是,它确实优先考虑别名和 shell 函数。这不适用于您的情况,因为如果您有其中任何一个,where
也会列出这一点。
在您的情况下,如果where
和ocamlc
命令已在同一个 shell 中执行,并且按该顺序,您可以非常确定会ocamlc
执行/home/choeger/ueb/uebb/amsun-integration/Runtime/test_src/../../opam/4.02.3/bin/ocamlc
. 您是否尝试通过此绝对路径显式运行 Ocam?我打赌你会得到相同的输出。
顺便说一句type -a
,一般来说,会提供比where
.