zsh:没有这样的文件或目录:-但文件存在



背景:我已经有了一个工作别名my-tool,如下所示:

alias my-tool='~/path/to/src/my-tool.py'

我想要另一个依赖于该别名路径的别名(这样我就不会在两个地方写路径(:

alias other-tool=$'$(dirname $(dirname $(which my-tool | awk '{ print($NF) }')))/script/other-tool.sh'

其输出错误

zsh: no such file or directory: ~/path/to/script/other-tool.sh

但它是存在的!

奇怪的是,如果我用替换别名

alias other-tool=$'$(dirname $(dirname ~/path/to/src/my-tool.py))/script/other-tool.sh'

它是有效的,但我还是想避免两次进入~/path/to/..

很明显,awkdirnamewhich中都存在意外行为,有人能解释为什么会出现错误吗?

别名的开头有一个波浪号字符。当别名作为命令被调用时,这是有效的,因为别名扩展的结果会进行单词扩展。但随后您尝试对别名的文本进行一些处理,这会产生一个要用作路径的字符串。该字符串仍然包含波浪号字符,因此您尝试使用名为~的目录。

如果您真的想使用my-tool别名作为定义other-tool别名的基础,请在定义别名时进行字符串处理。不要使用typewhich:它们是显示附加消息的最终用户命令。使用aliases关联数组直接获取别名的文本。使用zsh的内置构造来操作字符串(参数扩展(或路径(历史修饰符(:它们比使用外部工具更容易正确。

alias other-tool=$aliases[my-tool]:h:h/scripts/other-tool.sh

alias other-tool=${aliases[my-tool]%/*/*}/scripts/other-tool.sh

但是,用根路径定义一个变量,并在两个别名中使用该变量,在概念上更简单,也更可靠。

tool_root=~/path/to
alias my-tool='$tool_root/src/my-tool.py'
alias other-tool='$tool_root/scripts/other-tool.py'

肯定有更好的方法可以做到这一点(我喜欢@Luuk在评论中提到的路径前缀变量(,但与您尝试的方法等效的工作方法是:

alias other-tool=$'loc=($(type my-tool)); ${~loc[-1]:h:h}/script/other-tool.sh'

这不是每次运行别名时都运行awk和几个dirname进程,而是使用zsh参数子例程集成-首先,它将loc数组变量设置为运行type my-tool的结果,每个单词都有自己的元素,然后对于最后一个元素(路径(::h修饰符的作用类似于dirname,执行两次,然后~打开该扩展的GLOB_SUBST选项,该选项执行文件名扩展,捕获~

我处理波浪号(~(的方法只是将其展开一次,而不是用单引号('(硬引用它们-这样我就不必手动用"${HOME}":替换它

testfn="$( grealpath -ePq ~/.zshenv )"   # g- for gnu
echo "${testfn}"
ls -AlF "${testfn}"
/Users/user123/.bash_profile
-rw-r--r--  1 user123  staff  1746187 Aug 27 23:54 /Users/user123/.bash_profile

这实际上是正确的输出,因为我的zsh环境文件实际上是一个符号链接:

lr--r--r--  1 user123  staff  15 Dec 31  2019 /Users/user123/.zshenv -> ./.bash_profile

相关内容

  • 没有找到相关文章

最新更新