没有cmd/c的forfiles

10 cmd forfiles

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

C:\>forfiles /c "cmd /c ping /a"
IP address must be specified.

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

C:\>forfiles /c "ping /a"
Usage: ping [-t] [-a] [-n count] [-l size] [-f] [-i TTL] [-v TOS]
            [-r count] [-s count] [[-j host-list] | [-k host-list]]
            [-w timeout] [-R] [-S srcaddr] [-4] [-6] target_name

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

MC *_* ND 16

这是最初的答案.请阅读下面的行,以便对问题进行全面分析,并提供更好的解决方法

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

forfiles /c "ping  /a"
Run Code Online (Sandbox Code Playgroud)

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

为什么?

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

不,它没有任何问题

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

forfiles 将API称为

CreateProcess('c:\windows\system32\ping.exe','/a', ....)
Run Code Online (Sandbox Code Playgroud)

也就是说,应用程序名称及其参数.很好,干净,但有问题,因为应用程序的第一个参数是/a

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

但是对于它的行为方式,CreateProcess来自from 的调用forfiles应该是任何一个

CreateProcess('c:\windows\system32\ping.exe','ping.exe /a', ....)
CreateProcess(NULL, 'c:\windows\system32\ping.exe /a', .... )
Run Code Online (Sandbox Code Playgroud)

因为几乎所有用C语言编程(以及遵循相同约定的更多语言)都期望argv[0](参数值表第一个位置)将是程序名称,并且argv[1](参数值表,第二个位置)将是第一个参数,并且因为在forfiles启动过程中不是这种情况,第一个参数将被忽略,因为第一个真实参数将被存储argv[0],而不是argv[1]

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

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

  • 其他人将删除空格并取第一个非空白数据argv[0](例如find)

  • 您可以考虑的任何其他行为都可以被tokenizer采用.

一旦tokenizer结束了它的工作,程序将处理参数并选择其中一个

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

  • 不要假设在命令行中找到什么并识别参数.

所以,太空解决方案不是一个防弹解决方案(谢谢你dbenham)

怎么解决?

由于问题是命令行参数中程序名称的使用以及以下参数的错误位置,最好的选项似乎包括它(我们可以包含任何要用作的东西argv[0],但是大多数程序都期望程序名称 ...)

forfiles /c "ping ping -a"
forfiles /c "find find /c /v 0x220x22 @path"
Run Code Online (Sandbox Code Playgroud)


dbe*_*ham 7

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
Run Code Online (Sandbox Code Playgroud)

但它没有找到FIND - 仍然错过了/ C(计数)选项:

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


---------- D:\TEST.TXT
line 1
Run Code Online (Sandbox Code Playgroud)

更安全的赌注似乎是添加一个额外的单个字符参数,只有一个插入空间.但我不知道这是否适用于所有外部命令.

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
Run Code Online (Sandbox Code Playgroud)