Windows命令提示符(cmd.exe
)有一个可选的/s
parameter,用于修改/c
(运行特定命令然后退出)或/k
(运行)的行为一个特定的命令,然后显示一个shell提示符)。这个/s
参数显然与某些神秘的引用处理有关。
The docs令人困惑,但据我所知,当您执行cmd /c
something
和 something
时包含引号,默认情况下cmd
有时会删除这些引号,/s
会告诉它不要让它们单独使用。
我不明白的是,当引用删除会破坏任何内容时,因为这是唯一需要/s
(“禁止默认引用删除行为”)的时间。它只删除某些神奇条件下的引号,其中一个条件是/c
后面的第一个字符必须是引号。因此,它不会删除参数周围的引号;它要么删除正在运行的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"
可以正常工作。) /s
是否有一些微妙的东西在逃避我?什么时候有必要?什么时候会有什么不同?
答案 0 :(得分:16)
Cmd / S非常有用,因为它可以节省您不必担心“引用引号”。回想一下,/C
参数意味着“执行此命令,就像我在提示符下键入它一样,然后退出”。
因此,如果您有一个复杂的命令要传递给CMD.exe,您必须记住CMD的参数引用规则,并正确地转义所有引号,或使用/S
,这会触发特殊的非-darsing rule“Strip first and last "
并将所有其他字符视为执行不变的命令”。
您可以在想要利用CMD shell功能的地方使用它,而不是直接调用另一个程序。例如,环境变量扩展,输出或输入重定向,或使用CMD.exe内置插件。
示例:
使用内置shell:如果您在提示符下键入DEL /Q/S "%TMP%\TestFile"
,则执行此操作:
CMD.exe /S /C " DEL /Q/S "%TMP%\TestFile" "
这会执行SomeCommand.exe将标准输出重定向到临时文件并将标准错误重定向到同一位置:
CMD.exe /S /C " "%UserProfile%\SomeCommand.exe" > "%TMP%\TestOutput.txt" 2>&1 "
那么/S
给你额外的东西是什么?主要是它使您免于担心引用引号。如果您不确定例如环境变量是否包含引号字符,它也会有所帮助。只需说出/S
并在开头和结尾添加一个额外的引用。
模糊相关:Bourne Shell中的$ *。
一些背景
回想一下main()的参数列表是C-ism和Unix-ism。 Unix / Linux shell(例如Bourne Shell等)解释命令行,取消引用参数,将*
之类的通配符扩展到文件列表,并将参数列表传递给被调用程序。
所以,如果你说:
$ vi *.txt
vi命令可以看到这些参数:
vi
a.txt
b.txt
c.txt
d.txt
这是因为unix / linux在“参数列表”的基础上在内部运行。
最终从CP / M和VAX派生的Windows在内部不使用此系统。对于操作系统,命令行只是一个字符串。被调用程序负责解释命令行,展开文件globs(*
等)并处理不引用的引用参数。
所以C期望的参数必须被C运行时库破解。操作系统只提供带有参数的单个字符串,如果您的语言不是C(或者即使它是),它可能不会被解释为根据shell规则引用的空格分隔的参数,而是完全不同的东西。 / p>
答案 1 :(得分:10)
这是一个如何产生影响的例子。
假设您有两个可执行文件:c:\Program.exe
和c:\Program Files\foo.exe
。
如果你说
cmd /c "c:\Program Files\foo"
你将运行foo.exe
(没有参数),如果你说
cmd /s /c "c:\Program Files\foo"
您将以Program.exe
作为参数运行Files\foo
。
(奇怪的是,在第一个示例中,如果foo.exe
不存在,则Program.exe
将会运行。)
附录: 如果您要输入
c:\Program Files\foo
在命令提示符下,您将运行Program.exe
(与cmd / s / c一样)而不是foo.exe
(与cmd / c一样)。因此,如果要确保以与在命在Michael Burr链接的问题中,这可能更有可能是需要的,其中cmd.exe由CreateProcess而不是批处理文件或命令行本身启动。
也就是说,如果你说
CreateProcess("cmd.exe", "cmd /s /c \"" MY_COMMAND "\"", ...)
然后将解析字符串MY_COMMAND
,就像在命令提示符下键入它一样。如果您正在从用户那里获取命令行输入,或者您正在处理应用程序提供的命令行,那么这可能是一个好主意。例如,C运行时库system()函数可能以这种方式实现。