PowerShell и cmd возвращают разные результаты - PullRequest
0 голосов
/ 02 июня 2018

Почему они дают разные результаты?Чего мне не хватает в команде 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

Ответы [ 3 ]

0 голосов
/ 02 июня 2018

Это происходит из-за каретки ^.Вы пытаетесь избежать канала | для интерпретатора команд, но вам это не нужно, поскольку он уже находится в строке в кавычках, поэтому он не интерпретируется и отправляется непосредственно в 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 результатов.

0 голосов
/ 02 июня 2018

В дополнение к полезному ответу briantist с перспективой cmd.exe:

  • В cmd.exe, ^ служит только escape-символом в без кавычек строки.

  • Внутри двойные кавычки строки ("..."):

    • только символ, который необходимо экранировать, сам по себе ".
    • ^ не имеет специального значения и сохраняется как есть.

Учитывая, чтосимвол |, который вы намереваетесь передать в PowerShell, находится внутри "...", поэтому вам не нужно - и не нужно - использовать ^ для его выхода.

0 голосов
/ 02 июня 2018

Я думаю, что -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"
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...