Параметр Powershell, кажется, усекает значение

У меня есть сценарий Powershell, который отлично работает в VSCode, но из подсказки Powershell я получаю сообщение об ошибке. Ниже приведен вывод.

→ C:\WINDOWS\system32› powershell.exe -file 'D:\Source\Repos\Powershell Scripts\SD-Report-Archive.ps1' -sourcePath 'D:\Archives\' -targetPath 'D:\Archives2\'
D:\Archives\
Get-ChildItem : Cannot find path 'D:\A' because it does not exist.
At D:\Source\Repos\Powershell Scripts\SD-Report-Archive.ps1:25 char:14
+     $files = Get-ChildItem -Recurse -File -Path $sourcePath
+              ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : ObjectNotFound: (D:\A:String) [Get-ChildItem], ItemNotFoundException
    + FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.GetChildItemCommand

Как вы можете видеть во 2-й строке вывода, я делаю запись-вывод значения параметра, которое я отправляю, и это правильно. Когда я запускаю Get-ChildItem, кажется, что значение усекается до «D:\A», и я не знаю, почему.

Param(
    [Parameter(Mandatory = $true)]
    [string]$sourcePath,
    [Parameter(Mandatory = $true)]
    [string]$targetPath
)

function Copy-FilesIntoFolders {
    param()

    Write-Output $sourcePath;

    $files = Get-ChildItem -Path $sourcePath -Recurse -File
...
}

person Tim    schedule 17.10.2019    source источник
comment
У вас есть такая же проблема, если вы удалите обратную косую черту из ваших путей?   -  person TheMadTechnician    schedule 18.10.2019
comment
@TheMadTechnician Нет. Большое спасибо. Никогда бы не подумал, что это проблема.   -  person Tim    schedule 18.10.2019
comment
Я только что нашел этот пост, который, кажется, связан с тем, кто посетит этот пост в будущем. Это может быть причиной такого поведения. stackoverflow.com/questions/5079413/. Ключевое утверждение, которое следует принять во внимание, заключается в том, что powershell.exe не полностью оценивает аргументы скрипта при использовании параметра -File.   -  person Tim    schedule 18.10.2019
comment
У меня работает из того, что показано. Может быть, лучше показать весь сценарий.   -  person js2010    schedule 18.10.2019
comment
@Tim, связанный пост не имеет отношения к делу (это отдельная ошибка); ваша проблема связана исключительно с неработающим закулисным повторным цитированием PowerShell.   -  person mklement0    schedule 18.10.2019
comment
@mklement0 спасибо за обновление. Просто немного вернемся к сцене PowerShell. Я поражен тем, во что он вырос и что может сделать.   -  person Tim    schedule 18.10.2019


Ответы (2)


В Windows PowerShell по необходимости перестраивает командную строку для вызова внешних программ.

Примечательно, что большинство внешних программ не понимают строки в одинарных кавычках ('...') через интерфейс командной строки, поэтому выполнив собственный синтаксический анализ, PowerShell повторно заключает в кавычки результирующие (строчные) аргументы с использованием двойных кавычек ("..."), если сочтет это необходимым.

К сожалению, это повторное цитирование нарушено в нескольких отношениях:

  • Если значение аргумента не содержит пробелов, применяется без кавычек. Поэтому значения без пробелов, но со специальными символами могут нарушить работу команд, особенно при вызове другой оболочки, например cmd.exe.

    • E.g., cmd /c echo 'a&b' breaks, because a&b is ultimately passed without quotes, and & has special meaning in cmd.exe
  • Если аргумент имеет встроенные двойные кавычки (" символов), повторные кавычки не автоматически экранируют их для синтаксически правильного встраивания внутри "..." или использования без кавычек:

    • Например, foo.exe 'Nat "King" Cole' преобразуется в foo.exe "Nat "King" Cole" — обратите внимание на отсутствие экранирования внутренних символов ". - что приводит к другой строке при анализе большинством приложений, а именно Nat King Cole (без двойных кавычек).

    • Вы должны выполнять экранирование вручную, в дополнение к собственным требованиям PowerShell по экранированию, если применимо: foo.exe 'Nat \"King\" Cole' или, с двойными кавычками,
      foo.exe "Nat \`"King\`" Cole" (sic).

  • Точно так же, как и в вашем случае, если аргумент содержит пробелы и заканчивается на \, то конечный \ не экранируется в результирующей строке в двойных кавычках, что нарушает синтаксис аргумента :

    • Например, foo.exe 'a b\' c становится foo.exe "a b\" c, однако большинство программ, включая собственный интерфейс командной строки PowerShell, интерпретируют \" как экранированный символ ". вместо закрывающей двойной кавычки, что приводит к неправильной интерпретации аргумента, слиянию его со следующим аргументом, что приводит к
      a b" c

    • Вы снова должны выполнить экранирование вручную, удвоив \:
      foo.exe 'a b\\' c

      • Alternatively, if the argument happens to be a directory path whose trailing \ is optional, simply omit the latter.
person mklement0    schedule 18.10.2019
comment
Поэтому я думаю, именно поэтому мы должны прыгать через обручи, чтобы отправить аргументы -Command через запланированную задачу. Я обнаружил, что мне нужно добавить & затем двойную одинарную кавычку для всех строковых значений, а затем закрыть двойную кавычку в конце. - person Tim; 18.10.2019
comment
@Tim: Если вы вызываете интерфейс командной строки PowerShell (powershell.exe) из вне PowerShell, применяются другие правила. С -File вам придется использовать строки в двойных-кавычках, но требование удваивать конечный \ остается в силе. Да, передача одного фрагмента кода PowerShell в -Command является жизнеспособным обходным путем, хотя существуют различия в поведении, особенно в отношении того, как определяется код выхода — см. stackoverflow.com/a/57443822/45375. - person mklement0; 18.10.2019
comment
спасибо за ссылку. Этот пост многое объясняет. - person Tim; 19.10.2019

Get-ChildItem: не удается найти путь «D:\A», так как он не существует.

Обратная косая черта (\) здесь выглядит как управляющий символ. Пожалуйста, попробуйте с \\

person goooooooo    schedule 18.10.2019
comment
Сообщение об ошибке связано с командлетом PowerShell. В PowerShell код \ не работает как escape-символ (эту функцию выполняет обратная кавычка (`)). - person mklement0; 18.10.2019