启动新终端时执行 zshrc 别名
zshrc alias gets executed when launching a new terminal
我正在使用 zsh
并且在我的配置中添加了另一个别名:
alias recursively_git_pull_all_repo="for dir in $(find . -name ".git"); do cd ${dir%/*}; git pull ; cd -; done"
然而,每次我打开一个新终端时,这个别名似乎都会被执行(或者至少它会大大减慢启动新终端的速度)。
如何添加这个别名而不在每次打开新终端时都启动它?
您可以将其放在函数中而不是别名中:
$ cat zshFunction
function recursively_git_pull_all_repo () {
echo "Executing code"
for dir in $(find . -name ".git"); do cd ${dir%/*}; git pull ; cd -; done
}
$ recursively_git_pull_all_repo
zsh: command not found: recursively_git_pull_all_repo
$ source zshFunction
$
$ recursively_git_pull_all_repo
Executing code
$
TL;DR (或者应该是 TL;WR - "too long, won't read"?)
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
.
解决方案
快速的解决方案是在声明别名时只使用单引号,这样命令和参数将在别名是 运行 时替换,而不是在声明时替换。
但是还有其他一些问题:
- 如果任何目录名称包含空格,这将失败,因为 for 会将其解释为两个值
- 如果您无法切换到找到的目录之一,
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
作为最后一个元素的路径。
- 您可以使用 glob 限定符来限制对满足特定条件的元素的扩展。在这种情况下
**/.git(/)
限定符 /
表示:"only directories".
- 您还可以将历史扩展修饰符作为 glob 限定符。这是通过
:
后跟修饰符完成的 - 在本例中为 h
,它删除了最后一个路径组件(如程序 dirname
或示例中的 ${dir%/*}
) .
- 您实际上不需要将目录更改为 git 存储库即可使用
git
;你可以告诉 git
在哪里工作 git -C <path>
- 因为您现在在循环中只有 运行ning 一个命令,您可以使用
for
的简短语法,意思是没有 do ...; done
。
有趣的事实:如果您使用 d
而不是 dir
,则 for
的另一种缩写形式和选项 GLOB_STAR_SHORT
已启用(需要 zsh >= 5.2) ,您可以使用:
for d (**.git(/:h))git -C $d pull
只比您的别名长4个字符。是的,我知道完成。但是也有历史搜索。
我正在使用 zsh
并且在我的配置中添加了另一个别名:
alias recursively_git_pull_all_repo="for dir in $(find . -name ".git"); do cd ${dir%/*}; git pull ; cd -; done"
然而,每次我打开一个新终端时,这个别名似乎都会被执行(或者至少它会大大减慢启动新终端的速度)。
如何添加这个别名而不在每次打开新终端时都启动它?
您可以将其放在函数中而不是别名中:
$ cat zshFunction
function recursively_git_pull_all_repo () {
echo "Executing code"
for dir in $(find . -name ".git"); do cd ${dir%/*}; git pull ; cd -; done
}
$ recursively_git_pull_all_repo
zsh: command not found: recursively_git_pull_all_repo
$ source zshFunction
$
$ recursively_git_pull_all_repo
Executing code
$
TL;DR (或者应该是 TL;WR - "too long, won't read"?)
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
.
解决方案
快速的解决方案是在声明别名时只使用单引号,这样命令和参数将在别名是 运行 时替换,而不是在声明时替换。
但是还有其他一些问题:
- 如果任何目录名称包含空格,这将失败,因为 for 会将其解释为两个值
- 如果您无法切换到找到的目录之一,
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
作为最后一个元素的路径。 - 您可以使用 glob 限定符来限制对满足特定条件的元素的扩展。在这种情况下
**/.git(/)
限定符/
表示:"only directories". - 您还可以将历史扩展修饰符作为 glob 限定符。这是通过
:
后跟修饰符完成的 - 在本例中为h
,它删除了最后一个路径组件(如程序dirname
或示例中的${dir%/*}
) . - 您实际上不需要将目录更改为 git 存储库即可使用
git
;你可以告诉git
在哪里工作git -C <path>
- 因为您现在在循环中只有 运行ning 一个命令,您可以使用
for
的简短语法,意思是没有do ...; done
。
有趣的事实:如果您使用 d
而不是 dir
,则 for
的另一种缩写形式和选项 GLOB_STAR_SHORT
已启用(需要 zsh >= 5.2) ,您可以使用:
for d (**.git(/:h))git -C $d pull
只比您的别名长4个字符。是的,我知道完成。但是也有历史搜索。