为什么这些结果不同?我对cmd命令缺少什么?
PS C:\src\t\cad> Get-ChildItem -Directory -Recurse -Path $Env:ProgramFiles -ErrorAction SilentlyContinue | Measure-Object
Count : 17381
来自cmd.exe:
10:28:18.87 C:\src\t\cad
C:>powershell -NoProfile -Command "Get-ChildItem -Directory -Recurse -Path '"%ProgramFiles%"' -ErrorAction SilentlyContinue ^| Measure-Object"
Count : 0
答案 0 :(得分:3)
这是因为插入符^
而发生的。您正在尝试为命令解释器转义管道|
,但您不需要因为它已经在带引号的字符串中,因此它不会被解释并直接发送到PowerShell。
因此,PowerShell看到了这一点:
Get-ChildItem -Directory -Recurse -Path 'C:\Program Files' -ErrorAction SilentlyContinue ^| Measure-Object
那为什么不起作用?
PowerShell命令的参数由空格分隔,如果参数未具体命名,则在可能的情况下按位置处理。
让我们看一个更简单的例子来证明:
Get-ChildItem -Path . ^
同样地,你会看到没有输出,但有了跟踪,我们可以看到原因:
Trace-Command -Name ParameterBinding -Expression { Get-ChildItem -Path . ^ } -PSHost
DEBUG: ParameterBinding Information: 0 : BIND NAMED cmd line args [Get-ChildItem] DEBUG: ParameterBinding Information: 0 : BIND arg [.] to parameter [Path] DEBUG: ParameterBinding Information: 0 : COERCE arg to [System.String[]] DEBUG: ParameterBinding Information: 0 : Trying to convert argument value from System.String to System.String[] DEBUG: ParameterBinding Information: 0 : ENCODING arg into collection DEBUG: ParameterBinding Information: 0 : Binding collection parameter Path: argument type [String], parameter type [System.String[]], collection type Array, element type [System.String], coerceElementType DEBUG: ParameterBinding Information: 0 : Creating array with element type [System.String] and 1 elements DEBUG: ParameterBinding Information: 0 : Argument type String is not IList, treating this as scalar DEBUG: ParameterBinding Information: 0 : COERCE arg to [System.String] DEBUG: ParameterBinding Information: 0 : Parameter and arg types the same, no coercion is needed. DEBUG: ParameterBinding Information: 0 : Adding scalar element of type String to array position 0 DEBUG: ParameterBinding Information: 0 : BIND arg [System.String[]] to param [Path] SUCCESSFUL DEBUG: ParameterBinding Information: 0 : BIND POSITIONAL cmd line args [Get-ChildItem] DEBUG: ParameterBinding Information: 0 : BIND arg [^] to parameter [Filter] DEBUG: ParameterBinding Information: 0 : BIND arg [^] to param [Filter] SUCCESSFUL DEBUG: ParameterBinding Information: 0 : BIND cmd line args to DYNAMIC parameters. DEBUG: ParameterBinding Information: 0 : DYNAMIC parameter object: [Microsoft.PowerShell.Commands.GetChildDynamicParameters] DEBUG: ParameterBinding Information: 0 : MANDATORY PARAMETER CHECK on cmdlet [Get-ChildItem] DEBUG: ParameterBinding Information: 0 : CALLING BeginProcessing DEBUG: ParameterBinding Information: 0 : CALLING EndProcessing
该插入符号位于-Filter
参数的位置。 似乎过滤相当宽松,因为它不关心这个值是无意义的;我想它只是将它视为不匹配而且不会抛出错误。
根据mklement0的评论:
^
在技术上是有效的文件名,-Filter
接受文件名 (模式);因此,如果你有一个名为^
的文件,那就是。{ 匹配。使用非法的文件名字符(因字符而异) 平台)确实打破了,虽然错误消息的帮助 而变化。
所以-Filter ^
所拥有的是一个永不匹配的过滤器,因此结果为0。
答案 1 :(得分:1)
我认为-ErrorAction SilentlyContinue
正在抑制第一个命令中的错误,因此没有任何内容传递到管道Measure-Object
。
在PSCore上测试这个我得到:
pwsh -command "get-process ^| measure-object"
get-process : Cannot find a process with the name "^".
Count : 0
但删除' ^'字符:
bash-3.2$ pwsh -command "get-process | measure-object"
Count : 318
所以我认为对于Windows PowerShell来说是一样的。尝试没有^
powershell -NoProfile -Command "Get-ChildItem -Directory -Recurse -Path '"%ProgramFiles%"' -ErrorAction SilentlyContinue | Measure-Object"
答案 2 :(得分:1)
使用cmd.exe
视角来补充briantist's helpful answer:
在cmd.exe
中,^
仅用作未加引号字符串中的转义字符。
内部双引号字符串("..."
):
"
。^
没有特殊含义,并按原样保留。鉴于您打算传递给PowerShell的|
字符位于"..."
内,因此您不必 - 也不能 - 使用^
来逃避它。