Подтвердить что ты не робот

Is Get-ChildItem -Recurse нарушена, когда на входном пути есть квадратные скобки?

ОК, поэтому я чувствую, что это должно быть ошибкой в ​​PowerShell, но я хотел посмотреть, считаете ли вы, что это звучит сломанно. Это довольно простая вещь для воспроизведения, но я могу понять, почему это может быть не очень распространенный случай использования. Шаги, которые я приводил ниже, на самом деле не то, что делал мой script, я фактически вычислял размеры вложенных папок - я только что сговорил его до самого простого сценария, который показывает мою проблему.

Я только пробовал это на PowerShell 5.0.10240.16384, но вскоре может проверить его на более ранней версии [ Изменить:. Теперь я тестировал это на PowerShell 2.0, и ошибка не в этой версии - работает как ожидается]. Просто быстрая заметка - я использовал gci всюду как аббревиатуру для Get-ChildItem. Если вы еще этого не знаете, это работает, чтобы на самом деле ввести в PowerShell. Но проблема существует независимо от того, какой вы используете.

Сначала создайте папку с именем Test [123] где-нибудь удобным. В этой папке создайте пару файлов. Мои кадры Test1.txt и Test2.txt. Им не нужно ничего иметь.

Затем откройте сеанс PowerShell и Set-Location в родительскую папку вашей новой папки Test [123].

Теперь запустите gci -Filter Test*, и вы увидите что-то вроде:

Mode                LastWriteTime         Length Name
----                -------------         ------ ----
d-----       11/15/2015   3:22 PM                Test [123]

Все хорошо, правда? Затем попробуйте gci -Filter Test* | gci. Это делает вывод первого gci входным для следующего, то есть показывает нам детей каждого элемента, который возвращает первый gci. Это дает нам следующее:

Mode                LastWriteTime         Length Name
----                -------------         ------ ----
-a----       11/14/2015  10:21 PM              0 Test1.txt
-a----       11/15/2015   3:55 PM              0 Test2.txt

Опять же, все хорошо - точно так, как ожидалось. Это все файлы из нашей папки Test [123].

Теперь попробуйте следующее: gci -Filter Test* | gci -Recurse. Все, что мы изменили, это то, что второй вызов gci теперь рекурсивный, поэтому он должен показывать нам все файлы, включая подпапки. У нас нет подпапок, поэтому мы ожидаем тех же результатов, верно?

Неправильно. Мы вообще ничего не получаем. Кажется очень странным, что все, что мы сделали, добавлено -Recurse, и теперь мы получаем разные результаты. Я думаю, что добавление -Recurse никогда не должно выводить меньше вывода, только когда-либо.

Вот следующая странная вещь. Теперь попробуйте gci -Filter Test* | gci -Recurse -Name. Это то же самое, что и раньше, кроме параметра -Name. Это просто означает, что мы хотим получить тот же результат, за исключением того, что нам нужны только имена файлов, а не полная информация о каждом элементе. Поэтому мы, вероятно, ничего не ожидаем. Но это не то, что мы получаем, мы получаем следующее:

Test1.txt
Test2.txt

Это должно быть нарушено, не так ли? Во-первых, -Recurse никогда не должен уменьшать объем вывода, а во-вторых, запрашивать вывод в другом формате, не следует изменять объем вывода, который мы получаем.

Это происходит только при наличии квадратных скобок в имени папки. Если вы создадите другую папку, просто вызвав Test, и запустите все вышеперечисленные команды, вы всегда увидите файлы из папки Test.

Мои исследования привели меня к параметру -LiteralPath; однако, перефразировав вышеуказанную команду как gci -Filter Test* | foreach { gci -Recurse -LiteralPath $_ }, чтобы использовать этот параметр, по-прежнему не возвращает выход, и снова добавление параметра -Name запускает возвращаемые файлы.

Мне удалось сделать обходной путь для этого, используя параметр -Name, а затем объединив его с контуром папки, которую я ищу, а затем передал ее в Get-Item, но это сделало код длиннее и чем он должен быть.

Итак, мой вопрос: я допустил ошибку или что-то неправильно понял? Или это ошибка, о которой я должен сообщить?

4b9b3361

Ответ 1

Похоже на ошибку, сообщенную здесь или очень похожую проблему.

Ответ 2

TL; DR: используйте -LiteralPath для папки, когда в именах могут присутствовать необычные символы (включая квадратные скобки).


Я не смог воспроизвести это согласно OP в PowerShell v5.1.17134.590.

Однако я смог воспроизвести нечто подобное, используя следующую команду, чтобы попытаться перечислить файлы в папке, которая, как я подозревал, была пустой, чтобы удалить ее. На самом деле в этой папке было 12 файлов .mp3:

[PS]> gci '.\Music\Artist - Name\Album Name [Disc 1]\'

[PS]>

При добавлении переключателя -Recurse командлет возвращал ошибку, а не (вводящий в заблуждение) пустой ответ, показанный выше. Я протестировал ту же команду с -Include *, и все равно результатов не было, однако на этот раз не было ошибки при сочетании с переключателем -Recurse.

-LiteralPath

Для меня лучше всего было указать путь с параметром -LiteralPath:

[PS]> gci -LiteralPath '.\Music\Artist - Name\Album Name [Disc 1]\'

Спасаясь

Чтобы охватить некоторые другие возможные случаи, вы можете попытаться избежать квадратных скобок. Используя предложение @PetSerAl в комментариях к OP, вы можете попробовать что-то вроде этого:

[PS]> [System.Management.Automation.WildcardPattern]::Escape('.\Music\Artist - Name\Album Name [Disc 1]\')

.\Music\Artist - Name\Album Name '[Disc 1']\

К сожалению, это не сработало сразу. Я обнаружил, что мне нужно дважды убежать, и затем следующая команда выдала правильный список каталогов:

[PS]> gci '.\Music\Artist - Name\Album Name ''[Disc 1'']\'

Смотрите следующие вопросы и ответы, чтобы узнать больше о квадратных скобках и экранировании: