我正在使用zsh
,并在我的配置中添加了另一个别名:
alias recursively_git_pull_all_repo="for dir in $(find . -name ".git"); do cd ${dir%/*}; git pull ; cd -; done"
但是,此别名似乎在每次打开新终端时都会执行(或者至少会大大减慢启动新终端的速度)。
每次打开新终端时,如何在不启动别名的情况下添加它?
最佳答案
TL; DR (或者应该是TL; WR-“太长,无法阅读”?)
alias recursively_git_pull_all_repo='for dir in **/.git(/:h); git -C $dir pull'
您至少部分正确的是,在声明别名时运行了此命令的一部分。这有两个效果:
解释
您在用双引号声明别名,这允许参数扩展。这意味着在声明别名时,部分
$(find . -name ".git")
和${dir%/*}
将被扩展并替换为它们当时所产生的值。对于
$(find . -name ".git")
,这意味着.
最有可能是$HOME
,并且该结构由换行分隔的列表替换,该列表以换行分隔的列表包含主目录中的所有.git
目录(以及其他类似文件的对象)。${dir%/*}
可能会替换为空字符串,因为很可能未设置dir
。请记住:别名本身当时未执行,因此dir
循环不会设置for
。这意味着:
alias recursively_git_pull_all_repo="for dir in $(find . -name ".git"); do cd ${dir%/*}; git pull ; cd -; done"
将有效地保存为类似
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"
幸运的是,由于第一个存储库之后的换行符,此操作将失败并出现
zsh: command not found: docs/repo2/.git
错误。如果没有,它将反复进入您的主目录(不带参数的cd
),然后尝试执行git pull
。解决方案
快速的解决方案是在声明别名时仅使用单引号,这样在别名运行时(而不是在声明别名时)将替换命令和参数。
但是仍然存在其他一些问题:
git pull
将从当前目录运行。如果未在路径中的目录上设置execute标志,则实际上会发生这种情况。 find
还将列出名为.git
的非目录我建议使用
zsh
提供的内容来代替:alias recursively_git_pull_all_repo='for dir in **/.git(/:h); git -C $dir pull'
find
即可获取目录列表。 **
glob将被递归扩展到所有目录。因此,**/.git
将扩展到以.git
作为最后一个元素的所有路径。 **/.git(/)
限定词/
的意思是:“仅目录”。 :
后面加上修饰符完成的-在本例中为h
,它删除了最后一个路径组件(例如示例中的dirname
或${dir%/*}
程序)。 git
而将目录更改为git存储库;您可以告诉git
在哪里使用git -C <path>
for
使用简短语法,这意味着不使用do ...; done
。 有趣的事实:如果您使用
d
而不是dir
,则是另一种简短形式的for
,并且启用了GLOB_STAR_SHORT
选项(需要zsh> = 5.2),您可以使用:for d (**.git(/:h))git -C $d pull
仅比您的别名长4个字符。是的,我知道完成。但是也有历史搜索😉。
关于启动新终端时执行zshrc别名,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35895229/