我应该使用`sh -c \" ... \"`或`"!f(){...; }; F"在git别名脚本?

时间:2017-10-11 19:13:04

标签: git bash shell git-alias

我在编写带参数的git别名时已经湿透了。我见过一些人用

运行shell脚本
[alias]
  shAlias = !sh -c \" ... \"

和其他人使用

运行功能
[alias]
  fAlias = "!f() { ... ; }; f"

似乎(一旦我开始加速Bash - 这还不是我现在的地方)我想做的任何事情都可以用任何一种形式来实现。

在什么情况下优先于另一种?

除了可行性,是否有处理差异?内存使用/速度/等?

2 个答案:

答案 0 :(得分:5)

TL; DR:对最简单的命令使用函数方法,并在引用出现任何问题时切换到外部脚本。一起避免sh -c

我们可以have a look at the git source。它以git特定方式解析引号,如果结果没有shell元字符(包括空格)则作为文件执行,否则执行等效的execlp("sh", "-c", "result \"$@\"", "result \"$@\"", args...)

基于此,创建别名的最佳方法是创建外部脚本并使用:

[alias]
 myAlias = !/path/to/script

它需要一个外部文件,但在所有其他方面它更好:

  • 您可以使用任何需要的翻译。您甚至可以运行bash代码,而其他表单只允许您运行sh代码(区别就像C ++ vs C)。
  • 除非您需要,否则不会启动其他shell。 git会直接execve您的可执行文件。
  • 不需要转义。它只是一个普通的脚本。
  • 不需要任何惊喜或git知识。它只是一个剧本。

根据你的建议,亚军是:

[alias]
  fAlias = "!f() { ... ; }; f"

这不太棒,因为:

  • 遗憾的是,您只能使用sh投放,因此不会使用任何bash功能。
  • shell始终启动,但至少它只是一个。
  • 引号需要一些git特定的转义。
  • 您需要了解git的转义,但通常可以在不知道它是如何执行命令的情况下顺利通过,因为您只是使用函数的参数。

最后一个是最糟糕的:

[alias]
  shAlias = !sh -c \" ... \"

太可怕了,因为:

  • 您只能使用sh
  • 运行
  • 没有充分的理由,它会开始一个额外的外壳。
  • 您需要 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

显然,使用脚本更好,或者最糟糕的是功能方法,直到你需要更容易引用的更复杂的命令。

答案 1 :(得分:2)

首选该函数,因为它是由执行别名的shell直接执行的。使用sh -c '...'会导致另一个进程启动。