TL;DR:对最简单的命令使用函数方法,一旦遇到任何引用问题,请切换到外部脚本。只是避免sh -c
全部一起。
We can 看一下 git 源码 https://github.com/git/git/blob/217f2767cbcb562872437eed4dec62e00846d90c/run-command.c#L243。它解析出 a 中的引号git
特定方式,如果结果没有 shell 元字符(包括空格),则作为文件执行,或者执行相当于execlp("sh", "-c", "result \"$@\"", "result \"$@\"", args...)
否则。
基于此,创建别名的最佳方法肯定是创建外部脚本并使用:
[alias]
myAlias = !/path/to/script
它需要一个外部文件,但在所有其他方面它都更好:
- 您可以与任何您想要的翻译一起运行。你甚至可以跑步
bash
代码,因为你问,而其他形式只允许你运行sh
代码(区别就像 C++ 与 C 一样)。
- 除非您愿意,否则不会启动其他 shell。
git
will execve
直接你的可执行文件。
- 不需要转义。这只是一个普通的脚本。
- 没有惊喜或
git
所需的知识。这只是一个脚本。
根据您的建议,亚军是:
[alias]
fAlias = "!f() { ... ; }; f"
这不太好,因为:
- 不幸的是你只能运行
sh
,因此不使用任何bash
特征。
- 总是会启动一个 shell,但至少它只是一个。
- Some
git
报价需要特定的转义。
- 你需要知道
git
的转义,但通常可以在不确切知道它如何执行命令的情况下完成,因为您只需使用函数的参数。
最后一个是迄今为止最糟糕的:
[alias]
shAlias = !sh -c \" ... \"
这很糟糕,因为:
- 你只能运行
sh
.
- 它会无缘无故地启动一个额外的 shell。
- 你需要both
git
逃脱以及额外的级别sh
逃跑。
- 您需要知道如何转义代码
sh
,如何双重转义git
, 如何git
追加"$@"
如果有其他参数,则传递给您的命令,并将其他参数传递为$1
, $2
.
为了演示实际差异,假设您想为此命令创建一个别名,以通过以下方式获取远程服务器上的路径ssh
:
ssh "$1" 'echo "$PATH"'
您可以将其逐字复制粘贴到文件中,添加 shebang,然后使用:
[alias]
get-remote-path = !/path/to/my/script
或者你可以添加一点git
转义并使用函数方法:
[alias]
get-remote-path = "!f() { ssh \"$1\" 'echo \"$PATH\"'; }; f"
或者我们可以费力地逃脱并再次逃脱sh -c
方法(不,没有最后一个词就不起作用):
[alias]
get-remote-path = !sh -c 'ssh \"$1\" '\\''echo \"$PATH\"'\\' cthulhu
显然,最好使用脚本,或者最坏的情况下使用函数方法,直到您需要可以轻松引用的更复杂的命令。