3

我怎样才能让 PowerShell 理解这种类型的事情:

Robocopy.exe | Find.exe "Started"

旧的命令处理器给出了结果,但我对如何在 PowerShell 中执行此操作感到困惑:

&robocopy | find.exe "Started"                #error
&robocopy | find.exe @("Started")             #error
&robocopy @("|", "find.exe","Started")        #error
&robocopy | &find @("Started")                #error
&(robocopy | find "Started")                  #error

本质上,我想将一个外部命令的输出通过管道传输到另一个外部命令中。实际上,我将调用 flac.exe 并将其导入 lame.exe 以将 FLAC 转换为 MP3。

干杯

4

3 回答 3

3

@Jobbo:​​ cmd 和 PowerShell 是两个不同的外壳。有时可以混合它们,但正如您从 Shay 的回答中意识到的那样,它不会让您走得太远。但是,您可能在这里问错了问题。

大多数情况下,您尝试解决的问题(例如通过管道连接到 find.exe)甚至都不是必需的。你在 Powershell 中确实有 find.exe 的等价物,实际上是更强大的版本:select-string

您始终可以运行命令并将结果分配给变量。

$results = Robocopy c:\temp\a1 c:\temp\a2 /MIR

结果将是 STRING 类型,并且您有许多工具可以对其进行切片和切块。

PS > $results |select-string "started"

  Started : Monday, October 07, 2013 8:15:50 PM
于 2013-10-08T00:19:11.687 回答
3

tl;博士

# Note the nested quoting. CAVEAT: May break in the future.
robocopy.exe | find.exe '"Started"'    

# Alternative. CAVEAT: doesn't support *variable references* after --%
robocopy.exe | find.exe --% "Started"

# *If available*, use PowerShell's equivalent of an external program.
# In lieu of `findstr.exe`, you can use Select-String (whose built-in alias is scs):
# Note: Outputs are *objects* describing the matching lines.
#       To get just the lines, pipe to | % ToString 
#       or - in PowerShell 7+ _ use -Raw
robocopy.exe | sls Started

如需解释,请继续阅读。


PowerShell确实支持进出外部程序的管道。

这里的问题是参数解析和传递之一:find.exe有一个奇怪的要求,即它的搜索词必须用文字双引号括起来。

cmd.exe中,简单的双引号就足够了:find.exe "Started"

相比之下,默认情况下,PowerShell 在传递参数之前预先解析参数,如果逐字参数值不包含空格,则去掉封闭的引号,这样find.exe只会看到Started而没有双引号,从而导致错误。

有三种方法可以解决这个问题:

  • PS v3+(仅当您的参数只是文字和/或环境变量时才可以选择) :,停止解析符号--%,告诉 PowerShell将命令行其余部分按原样传递给目标程序(参考环境变量,如果有的话, cmd 样式 ( )):%<var>%
    robocopy.exe | find.exe --% "Started"

  • PS v2也是如此,或者如果您需要在参数中使用 PowerShell变量:应用PowerShell 引用的外层(PowerShell 将去除单引号并将字符串的内容按原样传递给find.exe,并且包含完整的双引号):
    robocopy.exe | find.exe '"Started"'

    • 警告:此技术仅因破坏行为而起作用。如果此行为得到修复(修复可能需要选择加入),上述操作将不再有效,因为 PowerShell 将""Started""在幕后传递,这会中断调用 - 请参阅此答案以获取更多信息。
  • 如果有类似的PowerShell命令可用,请使用它,这样可以避免所有引用问题。在这种情况下,Select-Stringcmdlet,PowerShell 的更多 powershell 模拟findstr.exe,如上所示。

于 2016-03-14T04:33:13.860 回答
2

通过 cmd 调用它:

PS> cmd /c 'Robocopy.exe | Find.exe "Started"'
于 2013-10-07T09:25:39.700 回答