windows 什么是“cmd /s”?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/9866962/
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 09:23:03  来源:igfitidea点击:

What is `cmd /s` for?

windowscommand-prompt

提问by Joe White

The Windows command prompt (cmd.exe) has an optional /sparameter, which modifies the behavior of /c(run a particular command and then exit) or /k(run a particular command and then show a shell prompt). This /sparameter evidently has something to do with some arcane quote handling.

Windows 命令提示符 ( cmd.exe) 有一个可选/s参数,它可以修改/c(运行特定命令然后退出)或/k(运行特定命令然后显示 shell 提示符)的行为。这个/s参数显然与一些神秘的报价处理有关。

The docsare confusing, but as far as I can tell, when you do cmd /csomething, and the somethingcontains quotation marks, then by default cmdwill sometimes strip off those quotes, and /stells it to leave them alone.

文档令人困惑,但据我所知,当你这样做时cmd /csomethingsomething包含引号,然后默认情况下cmd有时会去掉这些引号,并/s告诉它不要管它们。

What I don't understand is when the quote removal would break anything, because that's the only time /s("suppress the default quote-removal behavior") would be necessary. It only removes quotes under a certain arcane set of conditions, and one of those conditions is that the first character after the /cmust be a quotation mark. So it's not removing quotes around arguments; it's either removing quotes around the path to the EXE you're running, or around the entire command line (or possibly around the first half of the command line, which would be bizarre).

我不明白的是,引用删除何时会破坏任何内容,因为这是唯一需要的时间/s(“抑制默认引用删除行为”)。它仅在一组特定的神秘条件下删除引号,其中一个条件是 之后的第一个字符/c必须是引号。所以它不会删除参数周围的引号;它要么删除您正在运行的 EXE 路径周围的引号,要么删除整个命令行周围的引号(或者可能是命令行的前半部分,这很奇怪)。

  • If the path to the EXE is quoted, e.g. cmd /c "c:\tools\foo.exe" arg1 arg2, then quotes are unnecessary, and if cmdwants to remove them, fine. (It won't remove them if the path has a space in the name -- that's another of the arcane rules.) I can't imagine any reason to suppress the quote removal, so /sseems unnecessary.
  • If the entire command line is quoted, e.g. cmd /c "foo.exe arg1 arg2", then it seems like quote removal would be a necessity, since there's no EXE named foo.exe arg1 arg2on the system; so it seems like opting out of quote removal using /swould actually break things. (In actual fact, however, it does not break things: cmd /s /c "foo.exe arg1 arg2"works just fine.)
  • 如果引用了 EXE 的路径,例如cmd /c "c:\tools\foo.exe" arg1 arg2,则不需要引号,如果cmd想删除它们,很好。(如果路径名称中有空格,它不会删除它们——这是另一个神秘的规则。)我无法想象有任何理由禁止引用删除,所以/s似乎没有必要。
  • 如果整个命令行都被引用,例如cmd /c "foo.exe arg1 arg2",那么似乎需要删除引用,因为foo.exe arg1 arg2系统上没有命名的 EXE ;所以似乎选择不使用引用删除/s实际上会破坏事情。(然而,实际上,它并没有破坏事物:cmd /s /c "foo.exe arg1 arg2"工作得很好。)

Is there some subtlety to /sthat's eluding me? When would it ever be necessary? When would it even make any difference?

有什么微妙之处让/s我望而却步吗?什么时候需要?它什么时候会有所作为?

回答by Ben

Cmd /S is very useful as it saves you having to worry about "quoting quotes". Recall that the /Cargument means "execute this command as if I had typed it at the prompt, then quit".

Cmd /S 非常有用,因为它使您不必担心“引用引号”。回想一下,该/C参数的意思是“执行此命令,就像我在提示符下键入它一样,然后退出”。

So if you have a complicated command which you want to pass to CMD.exe you either have to remember CMD's argument quoting rules, and properly escape all of the quotes, or use /S, which triggers a special non-parsing rule of "Strip first and last "and treat all other characters as the command to execute unchanged".

因此,如果您有一个复杂的命令要传递给 CMD.exe,您要么必须记住 CMD 的参数引用规则,并正确地转义所有引号,要么使用/S,这会触发“先剥离并删除”的特殊非解析规则最后"并将所有其他字符视为命令执行不变”。

You would use it where you want to take advantage of the capabilities of the CMD shell, rather than directly calling another program. For example environment variable expansion, output or input redirection, or using CMD.exe built-ins.

您可以在想要利用 CMD shell 功能的地方使用它,而不是直接调用另一个程序。例如环境变量扩展、输出或输入重定向,或使用 CMD.exe 内置程序。

Example:

例子:

Use a shell built-in: This executes as-if you had typed DEL /Q/S "%TMP%\TestFile"at the prompt:

使用内置的 shell:这就像您DEL /Q/S "%TMP%\TestFile"在提示符下键入一样执行:

CMD.exe /S /C " DEL /Q/S "%TMP%\TestFile" "

This executes SomeCommand.exe redirecting standard output to a temp file and standard error to the same place:

这将执行 SomeCommand.exe 将标准输出重定向到临时文件并将标准错误重定向到同一位置:

CMD.exe /S /C " "%UserProfile%\SomeCommand.exe" > "%TMP%\TestOutput.txt" 2>&1 "

So what does /Sgive you extra? Mainly it saves you from having to worry about quoting the quotes. It also helps where you are unsure whether for example an environtment variable contains quote characters. Just say /Sand put an extra quote at the beginning and end.

那么什么/S能给你额外的好处呢?主要是它使您不必担心引用引号。它也有助于您不确定例如环境变量是否包含引号字符。只需说/S并在开头和结尾加上额外的引用即可。

Vaguely Related: $* in Bourne Shell.

隐约相关:Bourne Shell 中的 $*。

Some background

一些背景

Recall that the list of arguments to main() is a C-ism and Unix-ism. The Unix/Linux shell (e.g. Bourne Shell etc) interprets the command line, un-quotes the arguments, expands wildcards like *to lists of files, and passes a list of arguments to the called program.

回想一下 main() 的参数列表是 C-ism 和 Unix-ism。Unix/Linux shell(例如 Bourne Shell 等)解释命令行,取消引用参数,将通配符扩展*为文件列表,并将参数列表传递给被调用的程序。

So if you say:

所以如果你说:

$ vi *.txt

The vi command sees for example these arguments:

例如,vi 命令可以看到这些参数:

vi
a.txt
b.txt
c.txt
d.txt

This is because unix/linux operates internally on the basis of "list of arguments".

这是因为 unix/linux 根据“参数列表”在内部运行。

Windows, which derives ultimately from CP/M and VAX, does not use this system internally. To the operating system, the command line is just a single string of characters. It is the responsibility of the called program to interpret the command line, expand file globs (*etc) and deal with unquoting quoted arguments.

最终衍生自 CP/M 和 VAX 的 Windows 在内部不使用该系统。对于操作系统来说,命令行只是一个字符串。被调用程序负责解释命令行、扩展文件 globs(*等)并处理未引用的引用参数。

So the arguments expected by C, have to be hacked up by the C runtime library. The operating system only supplies a single string with the arguments in, and if your language is not C (or even if it is) it may not be interpreted as space-separated arguments quoted according to shell rules, but as something completely different.

所以 C 期望的参数必须被 C 运行时库修改。操作系统只提供一个带有参数的字符串,如果你的语言不是 C(或者即使是),它可能不会被解释为根据 shell 规则引用的空格分隔参数,而是完全不同的东西。

回答by Harry Johnston

Here's an example of how it can make a difference.

以下是它如何发挥作用的示例。

Suppose you have two executables: c:\Program.exeand c:\Program Files\foo.exe.

假设您有两个可执行文件:c:\Program.exec:\Program Files\foo.exe.

If you say

如果你说

cmd /c "c:\Program Files\foo"

you'll run foo.exe(with no arguments) whereas if you say

你会跑foo.exe(没有参数),而如果你说

cmd /s /c "c:\Program Files\foo"

you'll run Program.exewith Files\fooas the argument.

你会碰到Program.exeFiles\foo作为参数。

(Oddly enough, in the first example, if foo.exedidn't exist, Program.exewould run instead.)

(奇怪的是,在第一个示例中,如果foo.exe不存在,Program.exe则会运行。)

Addendum:if you were to type

附录:如果你要输入

 c:\Program Files\foo

at the command prompt, you would run Program.exe(as happens with cmd /s /c) rather than foo.exe(as happens with just cmd /c). So one reason for using /s would be if you want to make sure a command is parsed in exactly the same way as if it were being typed at the command prompt. This is probably more likely to be desirable in the scenario in the question Michael Burr linked to, where cmd.exe is being launched by CreateProcess rather than from a batch file or the command line itself..

在命令提示符下,您将运行Program.exe(就像 cmd /s /c 那样)而不是foo.exe(就像 cmd /c 那样)。因此,使用 /s 的一个原因是,如果您想确保以与在命令提示符下键入的方式完全相同的方式解析命令。在 Michael Burr 链接的问题中,这可能更受欢迎,其中 cmd.exe 由 CreateProcess 启动,而不是从批处理文件或命令行本身启动。

That is, if you say

也就是说,如果你说

CreateProcess("cmd.exe", "cmd /s /c \"" MY_COMMAND "\"", ...)

then the string MY_COMMANDwill be parsed exactly as if it were typed at the command prompt. If you're taking command-line input from the user, or if you're a library processing a command line provided by an application, that's probably a good idea. For example, the C runtime library system() function might be implemented in this way.

那么字符串MY_COMMAND将被完全解析,就好像它是在命令提示符下键入的一样。如果您从用户那里获取命令行输入,或者如果您是一个处理应用程序提供的命令行的库,这可能是一个好主意。例如,C 运行时库 system() 函数可能以这种方式实现。