不带cmd/c的文件

不带cmd/c的文件,cmd,forfiles,Cmd,Forfiles,我可以使用 cmd/c,如预期 C:\>forfiles /c "cmd /c ping /a" IP address must be specified. 我必须使用cmd/c,即使路径上有外部命令?这是原始答案。请阅读下面这一行,了解问题的完整分析和更好的解决方法 在命令及其参数之间放置两个空格 forfiles /c "ping /a" 已编辑虽然发布的解决方案适用于OP问题,但它不是一个完整的答案,因为在某些情况下,此选项不起作用 为什么? 我开始调试forfiles参数解析例程,

我可以使用
cmd/c
,如预期

C:\>forfiles /c "cmd /c ping /a" IP address must be specified. 我必须使用
cmd/c
,即使路径上有外部命令?

这是原始答案。请阅读下面这一行,了解问题的完整分析和更好的解决方法

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

forfiles /c "ping  /a"

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

为什么?

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

不,没有问题

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

forfiles
调用API作为

CreateProcess('c:\windows\system32\ping.exe','/a', ....)
即应用程序名及其参数。漂亮、干净,但有问题,因为应用程序的第一个参数是
/a

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

但要使其以这种方式运行,从
forfiles
调用
CreateProcess
应该是

CreateProcess('c:\windows\system32\ping.exe','ping.exe /a', ....)
CreateProcess(NULL, 'c:\windows\system32\ping.exe /a', .... )
几乎所有使用C语言编程的人(以及更多遵循相同约定的语言)都希望
argv[0]
(参数值表第一位置)将是程序名,
argv[1]
(参数值表第二位置)将是第一个参数,由于在
forfiles
启动的进程中并非如此,第一个实数参数将被忽略,因为第一个实数参数将存储在
argv[0]
中,而不是
argv[1]

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

  • 他们中的一些人将添加的空格视为一个传统参数,它将存储在
    argv[0]
    中(mingw/gcc和VC中的标准标记器就是这样工作的)

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

  • 您认为标记器可以采用的任何其他行为

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

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

  • 对命令行中的内容不做任何假设,并确定参数

因此,太空解决方案不是防弹的解决方案(谢谢dbenham)

如何解决

由于问题在于命令行参数中缺少程序名,并且以下参数的位置不正确,因此最好的选项似乎包括它(我们可以包括任何用作
argv[0]
,但大多数程序都需要程序名…)


当且仅当您运行的是单个外部命令时,才可以避免使用
CMD/C
。如果要使用内部命令,或者要使用重定向、管道、命令串联等,则必须使用
CMD/C

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

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
它与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
但查找失败-仍然缺少/C(计数)选项:

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

+1、非常有趣的发现。但它并不总是有效的。看我的答案。这是一个非常奇怪的解决方案。O@StevenPenny,答案更新了“哑语法”的原因。@npocmaka,没有,直到现在还没有文档记录。回答已更新。@MCND你在那里做了一些很棒的工作。谢谢你努力解开迷雾!避免麻烦和深奥的细节,改用PowerShell。@Bill_Stewart这是为了当PowerShell被破坏时+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