启动新终端时执行 zshrc 别名

nha*_*nha 5 zshrc oh-my-zsh

我正在使用zsh并在我的配置中添加另一个别名:

alias recursively_git_pull_all_repo="for dir in $(find . -name ".git"); do cd ${dir%/*}; git pull ; cd -; done"
Run Code Online (Sandbox Code Playgroud)

但是,每次我打开一个新终端时,这个别名似乎都会被执行(或者至少它会大大减慢启动新终端的速度)。

如何在每次打开新终端时添加此别名而不启动它?

Ada*_*hon 7

TL;DR (或者应该是 TL;WR - “太长,不会读”?)

alias recursively_git_pull_all_repo='for dir in **/.git(/:h); git -C $dir pull'
Run Code Online (Sandbox Code Playgroud)

您至少部分正确,因为在声明别名时会运行此命令的一部分。这有两个影响:

  1. 加载别名需要时间
  2. 别名不起作用

解释

您在双引号中声明别名,这允许参数扩展。这意味着部分$(find . -name ".git")${dir%/*}将在声明别名时使用它们当时产生的值进行扩展和替换。

对于$(find . -name ".git")这意味着.最有可能$HOME与结构替换用换行分隔所有的清单.git目录,在你的home目录(和其他类似文件的对象)。

${dir%/*}可能会被替换为一个空字符串,因为dir很可能没有设置。记住:别名本身在那个时候并没有被执行,所以dir不会被for循环设置。

这意味着:

alias recursively_git_pull_all_repo="for dir in $(find . -name ".git"); do cd ${dir%/*}; git pull ; cd -; done"
Run Code Online (Sandbox Code Playgroud)

将有效地保存为类似

alias recursively_git_pull_all_repo="for dir in docs/repo1/.git
docs/repo2/.git
otherdocs/repo/.git
whatever/.git; do
cd ; git pull ; cd -; done"
Run Code Online (Sandbox Code Playgroud)

这将 - 幸运的是 -zsh: command not found: docs/repo2/.git由于第一个存储库之后的换行符而失败并出现错误。如果没有,它会反复切换到您的主目录(cd不带参数)并尝试执行git pull.

解决方案

快速的解决方案是在声明别名时只使用单引号,这样命令和参数将在别名运行时替换,而不是在声明时替换。

但是还有一些其他的问题:

  • 如果任何目录名称包含空格,这将失败,因为 for 会将其解释为两个值
  • 如果您无法切换到找到的目录之一,git pull将从当前目录运行。如果未在路径中的目录上设置执行标志,则实际上可能会发生这种情况。
  • 没有附加参数find也会列出命名的非目录.git

相反,我建议使用zsh必须提供的内容:

alias recursively_git_pull_all_repo='for dir in **/.git(/:h); git -C $dir pull'
Run Code Online (Sandbox Code Playgroud)
  • 您实际上不需要find获取目录列表。该**水珠将递归扩展到所有目录。So**/.git将扩展到所有路径.git为最后一个元素。
  • 您可以使用 glob 限定符将扩展限制为满足特定条件的元素。在这种情况下**/.git(/),限定词的/意思是:“仅目录”。
  • 您还可以将历史扩展修饰符作为全局限定符。这是通过:后跟修饰符来完成的 - 在这种情况下h,它删除了最后一个路径组件(如程序dirname,或${dir%/*}从您的示例中)。
  • 您实际上并不需要将目录更改为 git 存储库才能使用git;你可以告诉git在哪里工作git -C <path>
  • 由于您现在只在循环内运行一个命令,因此您可以使用 for 的简短语法for,即 no do ...; done

有趣的事实:如果您使用d替代dir,另一种简短形式forGLOB_STAR_SHORT启用该选项(需要 zsh >= 5.2),您可以使用:

for d (**.git(/:h))git -C $d pull
Run Code Online (Sandbox Code Playgroud)

仅比您的别名长 4 个字符。是的,我知道完成。但也有历史搜索。