繁体   English   中英

Windows 版 Git 中的 Bash:使用 CMD.exe /C 和 args 运行命令时很奇怪

[英]Bash in Git for Windows: Weirdness when running a command with CMD.exe /C with args

这更像是一个烦恼而不是一个问题,但我非常想了解这里的语义。

我想要做的就是在临时命令提示符会话上运行任意命令,该会话本身在 bash 会话下运行。

我的成功率为 50/50,因为某些命令按预期工作,而其他命令则不然。

我认为问题可能在于参数没有正确排列(即缺少或合并的参数)

我将尝试通过一系列命令和响应来解释我所说的奇怪是什么意思。 (我正在尝试将单词test打印在屏幕上。)

我在与 Git-1.8.4 捆绑的GNU bash 版本 3.1.0(1)-release (i686-pc-msys)下运行这些:

第一次尝试:

$ cmd /c echo test
Microsoft Windows [Version 6.1.7601]
Copyright (c) 2009 Microsoft Corporation.  All rights reserved.
c:\>

第二次尝试:

$ cmd '/c echo test'
test"

第三次尝试:

$ cmd "/c echo test"
test"

第四次尝试:

$ cmd /c\ echo\ test
test"

第五次尝试:

$ cmd "/c echo" test
'echo" test' is not recognized as an internal or external command,
operable program or batch file.

我真的很感激对上述行为的任何指示或见解,因为这对我来说是不直观的,让我发疯!

编辑:还有另一个问题与此类似,但实际上并非如此,主要是因为它是关于通过不需要任何参数的 CMD /C 运行批处理文件。

它并没有真正回答我关于如何为 Windows 命令行应用程序正确提供参数的问题,即使示例是关于 CMD / C 的,这里的答案也可以应用于许多其他 Windows 命令行应用程序。

这实际上记录在 ReleaseNotes 文件中(在您安装的 Git for Windows 的顶级文件夹中)

此外,必须特别注意传递 Windows 程序 Windows 路径,因为它们不知道 MSys 风格的 POSIX 路径——您可以使用类似 $(cmd //c echo "$POSIXPATH") 的东西。

如果您使用cmd //c echo test它会按预期工作。

$ cmd //c echo test
test

原因是试图确保 posix 路径最终正确传递给 git 实用程序。 出于这个原因,Git for Windows 包括一个影响命令参数的修改后的 MSYS 层。 您应该注意,Git for Windows 提供的 bash shell 和工具并不打算用作 Windows 的通用 unix 工具。 如果你想要一个通用的 unix 风格的工具集,那么你应该安装 MSYS 或 cygwin。 Git Bash shell 是为使用 git 设置的,有时会显示。

阅读这篇文章后,我找到了对我有用的解决方案:

$ cat gvim.sh
cmd << EOD
gvim $@
EOD
$

Windows 8.1、Git(版本 1.9.5-preview20141217)、GNU bash,版本 3.1.20(4)-release (i686-pc-msys)。

我能够在 Windows 上使用 gnu bash 来重现问题。

我不能完全建立一个没有任何引号的第一种形式的模式。 它似乎适用于 Windows ECHO 命令,但不适用于 DIR 等其他命令。 编辑- 结果是 gnu bash 在我的命令周围加上引号,所以echo test变成了"echo" "test" 引号导致 cmd.exe 查找外部命令而不是内部 ECHO 命令。 我碰巧有“echo.exe”,所以它似乎可以运行。 奇怪的是 test 周围的引号没有显示。 当我尝试运行 DIR 命令时,它完全失败,因为没有任何 DIR.EXE。

带有引号的后续形式(最后一个除外)或转义空格的工作方式与您所看到的相同 - 命令中有一个不需要的尾随引号。

我想不出一个干净的解决方案。 但是,我有一个丑陋的 hack 应该可以给你想要的结果。 只需在命令末尾连接一个 REM 命令。 REM 将注释掉不需要的尾随引用。 REM 后面有一个空格很重要,否则REM"将不会被识别为有效命令。以下任何一种都应该有效。

$ cmd '/c echo test&rem '
$ cmd "/c echo test&rem "
$ cmd /c\ echo\ test\&rem\ 

请注意,最后一个命令在反斜杠后有一个空格。

该技术几乎适用于您可能希望通过 CMD.EXE 执行的任何命令字符串。

正如我在此处解释的那样,在将现代 Git 用于 Windows 的 bash 时还有一个额外的选择

MSYS_NO_PATHCONV=1 cmd /c echo test

每次尝试的解释

TL; 博士

不幸的答案是在 Windows 中,可以通过多种方式解析参数,并且您必须在 bash 中以这样一种方式格式化您的输出,Windows 程序将按照期望的方式对其进行重新解析

第二、第三、第四次尝试实际上都是相同的

这与(在 cmd 中) > cmd "/c echo test" Windows cmd 仅使用"引号,因此在运行时之间的某处,您的(在 bash 中) $ cmd '/c echo test'将所有参数转换为"/c echo test" ,它很高兴解析.

因为从 bash 的角度来看,第 2/3/4 次尝试都是相同的,它们都给出了相同的响应。 令人惊讶的是"是由于 windows 如何仅使用"而不是'解析,因此它与> cmd "/c echo test"

第五次尝试

$ cmd "/c echo" test> cmd /c echo" test 。(我猜: /c后面的空格是可选的,所以 cmd 不会被/c echo作为文字的空格混淆由于第一个引号。)所以它试图执行不存在的命令echo" test 由于引用,空格被解释为文字。 同样,如果你已经完成了$ cmd "/c echo "test你会得到输出"test ,因为空间不再被视为文字,也不再是命令echo一部分

注意: > cmd "/c echo" test> cmd /c echo" test错误相同。我的猜测是 cmd 自己解析了/c之后的所有内容,所以初始的"没有影响,因为解析开始所有再次。 将其归结为特殊的cmd怪异之处。


这实际上可以使用 python for windows 重现,这与 msys/mingw/git/bash/glibc/etc 无关......

python -c "import subprocess; subprocess.Popen(['cmd', '/c echo test'])"

我注意到 git-bash 将/c参数视为 C: 驱动器:

C:\Windows\system32\cmd.exe C:/ echo test

由于dbenham 发现添加了双引号。 这回声test"例如:

cmd /c\ echo\ test

我需要相同的行(脚本)才能在 git-bash 和 Cygwin Bash 中工作。 唯一有效的方法是

cmd /c\ echo\ test\&rem\ 

(请注意,此行需要以空格结尾),以及

cmd << EOC
echo test
EOC

所以转义/c之后的每个空格在行尾添加\\&rem\\ (包括尾随空格),或者只是将命令包装在here document 中

所有这些可能取决于 git-bash 的版本和特定命令。 :-(

因为您提到您正在使用Git for Windows包,所以我想我会指出它包含winpty ,它似乎非常易读。

$ winpty echo test
test

$ site="Default Web Site"
$ winpty 'C:\Windows\System32\inetsrv\appcmd' list site "${site}" /text:ID
1

这似乎在 1.9.5.msysgit.1 下工作

!foo=`bar`
cmd //c \\\\unc-path\\with\\slashes -args \"Quoted Arguments $foo\"

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM