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

Get-ChildItem и неразрывное пространство

Во время работы с файловыми серверами я заметил одну странную папку, которая сломала мой script. Папка имеет имя, состоящее только из одного символа с значением ascii 160 (неразрывное пространство, NBSP). Визуально это имя совпадает с символом пробела.

Вкратце, я выполняю Get-ChildItem в этой папке и в нее входит бесконечный цикл. Команда в действительности выполняется против родительской папки, и она снова возвращает проблемную папку, поэтому мой script попал в бесконечный цикл.

Вы можете легко имитировать это в своей собственной среде. В папке C:\temp создайте новую папку, имя которой состоит только из NBSP. Вы можете набрать это с удерживанием alt и нажатием 0160 на цифровой клавиатуре. После его создания запустите

Get-ChildItem C:\Temp\ -Recurse

вы получите бесконечный список папок без имени, хотя у меня есть только одна папка.

d-----        6/15/2017   2:20 PM
d-----        6/15/2017   2:20 PM
d-----        6/15/2017   2:20 PM
d-----        6/15/2017   2:20 PM
d-----        6/15/2017   2:20 PM
. . .

Я тестировал это с помощью PowerShell 4 и 5, на сервере и клиентской ОС, и это же поведение. Команда Get-Item также выпускает это имя, и оба переключателя -Path и -LiteralPath ведут себя одинаково. Я также попробовал класс [System.IO.Directory], но он имел ту же проблему.

Вопрос: Я обновил свой script, чтобы сообщить о папках с этим именем как ошибке и пропустить его, но мне интересно, есть ли еще более умный способ сделать это? Моя цель состояла бы в том, чтобы запустить Get-ChildItem или эквивалент против такой папки.

Это известная проблема? Стоит ли сообщать об этом где-нибудь в качестве ошибки, если это подтвердится больше людей?

4b9b3361

Ответ 1

Как упоминалось в комментарии, вы обнаружили фактическую ошибку, которая, надеюсь, скоро будет исправлена.

Существует очень приемлемое обходное решение, которое можно применить с минимальными усилиями, продолжая использовать Get-ChildItem без необходимости исключать вашу папку.

Unicode-версия Get-ChildItem не страдает от этой проблемы. (Проверено на Powershell 5.1 в среде Windows 10) Чтобы использовать его, просто замените

Get-ChildItem  -Path 'c:\__tmp' -recurse 

Get-ChildItem  -LiteralPath '\\?\c:\__tmp' -recurse 

Дополнительная заметка

Если вам нужно иметь дело с UNC, вызов unicode UNC немного отличается.

Get-ChildItem  -LitteralPath '\\?\UNC\127.0.0.1\c$\__tmp' -recurse 

Обратите внимание, что для этого я правильно использую параметр -LiteralPath вместо -path.

Ссылки

Из документации Microsoft

-LiteralPath

Указывает путь к одному или нескольким местоположениям. В отличие от параметра -Path значение параметра -LiteralPath используется точно так же, как оно набирается. Никакие символы не интерпретируются как подстановочные знаки. Если путь содержит escape-символы, заключите его в одинарные кавычки. Одиночные кавычки указывают, что Windows PowerShell не интерпретирует символы как escape-последовательности.

источник

Относительно соглашения о префиксе unicode: Именование файлов, путей и пространств имен

Bonus Вызов Unicode также имеет преимущество для решения ограничения длины пути 260 символов: см. Здесь