windows 使用 cmd.exe 时如何处理引号字符

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/355988/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-09 05:50:37  来源:igfitidea点击:

How do I deal with quote characters when using cmd.exe

windowscommand-line

提问by Scott Langham

I'm trying to do this:

我正在尝试这样做:

cmd.exe /C "C:\Program Files\Somewhere\SomeProgram.exe" > "C:\temp\Folder Containing Spaces\SomeProgram.out"

However, I have problems which are down to the way cmd.exe works. If you read the help for it, it handles " characters in a special way. See the help at the end of question. So, this doesn't execute correctly... I'm guessing cmd.exe strips some quotes which makes the statement ill-formed.

但是,我遇到了与 cmd.exe 工作方式有关的问题。如果您阅读它的帮助,它会以特殊方式处理 " 字符。请参阅问题末尾的帮助。因此,这无法正确执行...我猜 cmd.exe 去掉了一些引号,这使得语句格式错误。

I can do this successfully:

我可以成功地做到这一点:

// quotes not required around folder with no spaces
cmd.exe /C "C:\Program Files\Somewhere\SomeProgram.exe" > C:\temp\FolderWithNoSpaces\SomeProgram.out

But, I really need the first one to work. Is there away around the strange quote processing that cmd.exe uses? I want it to preserve all of the quotes, but there doesn't appear to be an option to make it do that.

但是,我真的需要第一个工作。cmd.exe 使用的奇怪的报价处理是否存在?我希望它保留所有引号,但似乎没有办法让它这样做。



Help taken from output of: cmd /?

来自以下输出的帮助: cmd /?

If /C or /K is specified, then the remainder of the command line after the switch is processed as a command line, where the following logic is used to process quote (") characters:

如果指定了 /C 或 /K,则切换后的命令行的其余部分将作为命令行处理,其中使用以下逻辑处理引号 (") 字符:

1.  If all of the following conditions are met, then quote characters
    on the command line are preserved:

    - no /S switch
    - exactly two quote characters
    - no special characters between the two quote characters,
      where special is one of: &<>()@^|
    - there are one or more whitespace characters between the
      the two quote characters
    - the string between the two quote characters is the name
      of an executable file.

2.  Otherwise, old behavior is to see if the first character is
    a quote character and if so, strip the leading character and
    remove the last quote character on the command line, preserving
    any text after the last quote character.

回答by Scott Langham

Ah. doh. Think I've answered my own question.

啊。哦。认为我已经回答了我自己的问题。

If you use /S, and wrap the whole thing in quotes, it just removes those outer quotes.

如果您使用 /S,并将整个内容用引号括起来,它只会删除那些外部引号。

cmd.exe /S /C " do what you like here, quotes within the outermost quotes will be preserved "

回答by barlop

I think you'll find that your example works absolutely fine as it is.

我想你会发现你的例子完全正常。

cmd.exe /C "C:\Program Files\Somewhere\SomeProgram.exe" > "C:\temp\Folder Containing Spaces\SomeProgram.out"


I have reproduced your example here http://pastebin.com/raw.php?i=YtwQXTGN

我在这里复制了你的例子 http://pastebin.com/raw.php?i=YtwQXTGN

C:\>cmd /c "c:\Program Files\my folder\my long program.exe" > "c:\temp\spaces are here\a.a"

C:\>type "c:\temp\spaces are here\a.a"
my long program.exe has run

C:\>

further example demonstrating it works with "my long program.exe", removing cmd /c, it operates fine too.

C:\>"c:\Program Files\my folder\my long program.exe" > "c:\temp\spaces are here\
a.a"

C:\>type "c:\temp\spaces are here\a.a"
my long program.exe has run

C:\>



Another example, but with replace.  replace with no parameters says "source path required"  "no files replaced"

C:\>replace > a.a
Source path required

C:\>type a.a
No files replaced

Exactly the same effect when they're in folders with spaces.

C:\>cmd /c "c:\Program Files\my folder\replace.exe" > "c:\temp\spaces are here\r.r"
Source path required

C:\>type "c:\temp\spaces are here\r.r"
No files replaced

C:\>

further demonstration with replace
without cmd /c works fine too.

C:\>"c:\Program Files\my folder\replace.exe" > "c:\temp\spaces are here\r.r"
Source path required

C:\>type "c:\temp\spaces are here\r.r"
No files replaced

C:\>


The reason why your example works fine

你的例子工作正常的原因

cmd.exe /C "C:\Program Files\Somewhere\SomeProgram.exe" > "C:\temp\Folder Containing Spaces\SomeProgram.out"

and how/why it works the way it does, is because the > is interpreted as special by the host.exe So this part cmd.exe /C "C:\Program Files\Somewhere\SomeProgram.exe"- I think - is evaluated first. i.e. cmd /c does not see the > and after.

以及它如何/为什么以这种方式工作,是因为 > 被 host.exe 解释为特殊的所以这部分cmd.exe /C "C:\Program Files\Somewhere\SomeProgram.exe"- 我认为 - 首先被评估。即 cmd /c 没有看到 > 和之后。

cmd /? shows 2 cases

cmd /? 显示2个案例

Case 1 and Case 2. Your example fits Case 1

案例 1 和案例 2。您的示例适合案例 1

If /C or /K is specified, then the remainder of the command line after
the switch is processed as a command line, where the following logic is
used to process quote (") characters:

    1.  If all of the following conditions are met, then quote characters
        on the command line are preserved:

        - no /S switch
        - exactly two quote characters
        - no special characters between the two quote characters,
          where special is one of: &<>()@^|
        - there are one or more whitespace characters between the
          two quote characters
        - the string between the two quote characters is the name
          of an executable file.

    2.  Otherwise, old behavior is to see if the first character is
        a quote character and if so, strip the leading character and
        remove the last quote character on the command line, preserving
        any text after the last quote character.

You can test for sure that your example fits case 1, because if you add /s (without adding any more quotes or making any change at all to your example other than adding /s), then you get a different result, because it makes your example hit case 2. So that proves that your example is definitely a case 1. And it clearly meets all the criteria of case 1. If your example were a case 2, and you added /s, then it'd make no difference.

您可以测试以确保您的示例适合案例 1,因为如果您添加 /s(除了添加 /s 之外,不添加更多引号或对您的示例进行任何更改),那么您会得到不同的结果,因为它使您的示例符合案例 2。所以这证明您的示例绝对是案例 1。并且它显然符合案例 1 的所有标准。如果您的示例是案例 2,并且您添加了 /s,那么它没有任何区别.

Your answer is interesting because it shows an alternative way of getting your result, but in case 2. By adding additional outter quotes and adding /s.

您的答案很有趣,因为它显示了获得结果的另一种方法,但在情况 2 中。通过添加额外的外部引号并添加 /s。

But actually, when you add those additional outter quotes, then you've just made it a case 2, and adding a /s on top of that won't make a difference.

但实际上,当您添加这些额外的外部引号时,您只是将其设为案例 2,并且在其上添加 /s 不会产生任何影响。

C:\>cmd /c "c:\Program Files\my folder\replace.exe"
Source path required
No files replaced

C:\>cmd /s /c "c:\Program Files\my folder\replace.exe"
'c:\Program' is not recognized as an internal or external command,
operable program or batch file.

C:\>cmd /c ""c:\Program Files\my folder\replace.exe""
Source path required
No files replaced

C:\>cmd /s /c ""c:\Program Files\my folder\replace.exe""
Source path required
No files replaced

C:\>


The example in your question worked fine

您问题中的示例工作正常

cmd.exe /C "C:\Program Files\Somewhere\SomeProgram.exe" > "C:\temp\Folder Containing Spaces\SomeProgram.out"

Your alternative (with the /S and outer quotes) you give as an answer to make the example work, works fine too

您提供的替代方案(带有 /S 和外部引号)作为使示例工作的答案,也可以正常工作

cmd.exe /S /C ""C:\Program Files\Somewhere\SomeProgram.exe" > "C:\temp\Folder Containing Spaces\SomeProgram.out""

Though your answer which is an alternative, can actually be simplified by removing the /S because it's already a case 2, so adding /s won't make any difference. So this would improve the solution given in your answer

尽管您的答案是替代方案,但实际上可以通过删除 /S 来简化,因为它已经是第 2 种情况,因此添加 /s 不会有任何区别。因此,这将改进您的答案中给出的解决方案

cmd.exe /C ""C:\Program Files\Somewhere\SomeProgram.exe" > "C:\temp\Folder Containing Spaces\SomeProgram.out""

Your example which you described as a problem in your question, and your solution, produce the same good result. But one big difference I suppose, (and I am not sure how to test for it), but one difference in the way your example works, and the way the solution in your answer works, is I think in the case of your example, the hosting/invoking cmd.exe does the redirect to the file. Whereas in your solution's example, the invoked cmd.exe is passed the > by the host cmd.exe, and so the invoked cmd.exe does the redirect. Also of course, your example is a case 1, while your solution is an amendment you made (very well) to make it work in case 2.

您在问题中描述为问题的示例以及您的解决方案产生了同样好的结果。但是我认为有一个很大的不同(我不确定如何测试它),但是您的示例的工作方式以及您的答案中的解决方案的工作方式的一个差异是,我认为就您的示例而言,托管/调用 cmd.exe 会重定向到文件。而在您的解决方案示例中,调用的 cmd.exe 由主机 cmd.exe 传递 >,因此调用的 cmd.exe 执行重定向。当然,您的示例是案例 1,而您的解决方案是您(非常好)做出的修改,使其在案例 2 中起作用。

I hope I haven't erred here, I may have. But your question and answer did help me wrap my head around how cmd and in particular cmd /c is working!

我希望我没有在这里犯错,我可能有。但是您的问题和答案确实帮助我了解了 cmd,特别是 cmd /c 是如何工作的!

Perhaps your example was an oversimplification of your actual one, and your actual one did fail and needed your amendment. If your example case, had been a tiny bit more complex, by for example, having a parameter to the program that took quotes, then it'd fail Case 1, and you would indeed need outter quotes (/S would not change the result, so no /S would be necessary, as it'd already be a case 2 once you add those needed outer quotes). But the example you gave in your question actually seems to me to work fine.

也许你的例子是对你的实际例子的过度简化,而你的实际例子确实失败了,需要你的修正。如果您的示例案例稍微复杂一点,例如,通过为程序添加一个带引号的参数,那么它会失败案例 1,并且您确实需要外部引号(/S 不会改变结果,所以不需要 /S ,因为一旦你添加了那些需要的外部引号,它就已经是情况 2)。但是你在问题中给出的例子在我看来实际上工作正常。

Added- A related Q and A What is `cmd /s` for?

添加- 一个相关的 Q 和 A什么是`cmd /s`?