12

我可以按预期运行forfiles命令 cmd /c

C:\>forfiles /c "cmd /c ping /a"
必须指定 IP 地址。

但是,如果我删除cmd /c,它不再识别任何参数,只识别基本命令

C:\>forfiles /c "ping /a"
用法:ping [-t] [-a] [-n count] [-l size] [-f] [-i TTL] [-v TOS]
            [-r 计数] [-s 计数] [[-j 主机列表] | [-k 主机列表]]
            [-w 超时] [-R] [-S srcaddr] [-4] [-6] 目标名称

cmd /c即使在 PATH 上使用外部命令,我也必须使用吗?

4

2 回答 2

18

这是原始答案。请阅读下面的行,以获得对问题的完整分析以及解决问题的更好方法

在命令及其参数之间放置两个空格

forfiles /c "ping  /a"

编辑虽然发布的解决方案适用于 OP 问题,但它不是一个完整的答案,因为在某些情况下此选项不起作用。

为什么?

我开始调试forfiles参数解析例程,认为问题在于解析和转换命令字符串以生成最终运行命令的方式。

不,它可以正常工作

问题的原因在于对CreateProcessAPI 函数的调用、C 参数解析器的工作方式以及程序员通常如何处理参数。

forfiles将 API 调用为

CreateProcess('c:\windows\system32\ping.exe','/a', ....)

也就是说,应用程序名称和它的参数。漂亮干净,但有问题,因为应用程序的第一个参数是/a

哪里有问题?在第一个论点。几乎所有程序中的常用参数处理都假定程序的第一个参数是程序本身(至少是它的名称),即argv[0]程序名称。

但是为了让它表现得那样,对CreateProcessfrom的调用forfiles应该是

CreateProcess('c:\windows\system32\ping.exe','ping.exe /a', ....)
CreateProcess(NULL, 'c:\windows\system32\ping.exe /a', .... )

几乎每个用 C 语言(以及更多遵循相同约定的语言)编程的人都期望argv[0](arguments value table first position) 将是程序名称,而argv[1](arguments value table, second position) 将是第一个参数,并且因为在启动的进程中不是这种情况forfiles,所以第一个参数将被忽略,因为第一个真正的参数将存储在 中argv[0],而不是argv[1]

因此,正确的行为或失败将取决于被调用程序使用的解析器/词法分析器/标记器。

  • 他们中的一些人会将添加的空间视为将存储在内部的附加参数argv[0](mingw/gcc 和 VC 中的标准标记器以这种方式运行)。

  • 其他人将删除空格并将第一个非空白数据作为argv[0](的情况find

  • 分词器可以采用您认为的任何其他行为。

一旦标记器结束其工作,程序将处理参数并选择其中之一

  • 忽略第一个参数,因为它假定程序名称在这个位置

  • 对将在命令行中找到的内容不做任何假设并确定参数。

所以,空间解决方案不是万无一失的解决方案(谢谢dbenham)

如何解决?

由于问题是命令行参数中缺少程序名称,并且以下参数的位置不正确,因此最好的选择似乎包括它(我们可以包含任何要用作的内容argv[0],但正如大多数程序所期望的那样姓名 ...)

forfiles /c "ping ping -a"
forfiles /c "find find /c /v 0x220x22 @path"
于 2014-11-18T08:55:06.837 回答
8

CMD /C当且仅当您运行单个外部命令时,您才能避免。如果你想使用内部命令,或者如果你想使用重定向、管道、命令连接等,那么你必须使用CMD /C.

FORFILES 将参数传递给命令的方式有问题。正如 MC ND 所发现的,添加一个额外的空间对 PING 有效。但这似乎不适用于所有外部命令。

它适用于 PING、FINDSTR 和 HELP:

D:\>forfiles /m test.txt /c "ping  /a"

IP address must be specified.

D:\>forfiles /m test.txt /c "help  vol"

Displays the disk volume label and serial number, if they exist.

VOL [drive:]

D:\>forfiles /m test.txt /c "findstr  . @path"

line 1

但是 FIND 失败了 - /C (count) 选项仍然丢失:

D:\>forfiles /m test.txt /c "find  /c /v 0x220x22 @path"


---------- D:\TEST.TXT
line 1

一个更安全的选择似乎是添加一个额外的单个字符参数,中间只有一个空格。但我不知道这是否适用于所有外部命令。

D:\>forfiles /m test.txt /c "find x /c /v 0x220x22 @path"


---------- D:\TEST.TXT: 1

D:\>forfiles /m test.txt /c "ping x /a"

IP address must be specified.

D:\>forfiles /m test.txt /c "help x vol"

Displays the disk volume label and serial number, if they exist.

VOL [drive:]

D:\>forfiles /m test.txt /c "findstr x . @path"

line 1
于 2014-11-18T23:26:17.660 回答