Хабрахабр

Windows, PowerShell и длинные пути

Важное\____Новое____\!!! Думаю, вам, как и мне, не раз приходилось видеть пути вида \!!! о назначении Козлова Ивана Александровича временно исполняющим обязанности руководителя направления по сопровождению корпоративных VIP-клиентов и организации деловых встреч в кулуарах.doc. Не удалять!!!\Приказ №98819-649-Б от 30 февраля 1985г. Кто-то практикует workaround в виде мапирования дисков, кто-то использует файловые менеджеры, умеющие работать с длинными путями: Far Manager, Total Commander и им подобные. И зачастую открыть такой документ в Windows сходу не получится. The fully qualified file name must be less than 260 characters, and the directory name must be less than 248 characters.
Как оказалось, 260 символов хватит «не только лишь всем». А еще многие с грустью наблюдали, как созданный ими PS-скрипт, в который было вложено немало труда и который в тестовом окружении работал на ура, в боевой среде беспомощно жаловался на непосильную задачу: The specified path, file name, or both are too long. Если вам интересно выйти за границы дозволенного — прошу под кат.
Вот лишь некоторые из печальных последствий ограничения длины файлового пути:

Ей тоже не страшны длинные пути, да и умеет она многое. Немного отклоняясь от темы, замечу, что для DFS Replication рассматриваемая в статье проблема не страшна и файлы с длинными именами успешно путешествуют с сервера на сервер (если, конечно, в остальном вы всё сделали правильно).
Еще хотелось бы обратить внимание на очень полезную и не раз меня выручавшую утилиту robocopy. Если нужно пошаманить со списками контроля доступа в файловой системе (DACL), посмотрите в сторону subinacl. Поэтому если задача сводится к копированию/переносу файловых данных, можно остановиться на ней. Тут рассмотрены способы применения.
Мне же было интересно научить работать с длинными путями PowerShell. Несмотря на солидный возраст, отлично себя показала на Windows 2012 R2. С ним почти как в бородатом анекдоте про Ивана-Царевича и Василису Прекрасную.

Быстрый способ

Перейти на Linux и не париться Windows 10/2016/2019 и включить соответствующий параметр групповой политики/твикнуть реестр. Подробно на этом способе останавливаться не буду, т.к. в сети уже много статей на эту тему, например, эта.
Учитывая, что в большинстве компаний много, мягко говоря, не свежих версий операционных систем, способ этот быстрый только для написания на бумаге, если, конечно, вы не из тех счастливчиков, у которых мало legacy-систем и царят Windows 10/2016/2019.

Долгий способ

Тут сразу оговоримся, что изменения не затронут поведение проводника Windows, а дадут возможность использовать длинные пути в командлетах PowerShell, таких как Get-Item, Get-ChildItem, Remove-Item и др.
Для начала обновим PowerShell. Делается на раз-два-три.

  1. Обновляем .NET Framework до версии не ниже 4.5. Операционная система должна быть не ниже Windows 7 SP1/2008 R2. Актуальную версию загрузить можно здесь, дополнительную информацию почитать тут.
  2. Скачиваем и устанавливаем Windows Management Framework 5.1
  3. Перезагружаем машину.

Трудолюбивые могут сделать описанные выше шаги вручную, ленивые — с помощью SCCM, политик, скриптов и эникеев других средств автоматизации.

После обновления должно быть примерно так:

Теперь при использовании командлетов Get-ChildItem и ему подобных вместо привычного Path будем использовать LiteralPath.
Формат путей при этом будет немного другим:
Get-ChildItem -LiteralPath "\\?\C:\Folder"
Get-ChildItem -LiteralPath "\\?\UNC\ServerName\Share"
Get-ChildItem -LiteralPath "\\?\UNC\192. Текущую версию PowerShell можно узнать из переменной $PSVersionTable. 0. 168. 10\Share"

Для удобства преобразования путей из привычного формата в формат LiteralPath можно использовать вот такую функцию:
Function ConvertTo-LiteralPath
Else {Return "\\?\$Path"}
}

Обратите внимание, что при задании параметра LiteralPath нельзя использовать подстановочные символы (*, ? и т.д.)
Помимо параметра LiteralPath, в обновленной версии PowerShell командлет Get-ChildItem получил параметр Depth, с помощью которого можно задавать глубину вложенности для рекурсивного поиска, я пару раз его использовал и остался доволен.

Меня, например, очень выручил этот подход при написании скрипта для сбрасывания атрибута «временный» у файлов в DFSR-папках. Теперь можно не бояться, что ваш PS-скрипт собьется с долгого тернистого пути и не разглядит далекие файлы. От вас же жду интересных комментариев и предлагаю пройти опрос. Но это уже другая история, о которой я постараюсь рассказать в другой статье.

1. Полезные ссылки:
docs.microsoft.com/ru-ru/dotnet/api/microsoft.powershell.commands.contentcommandbase.literalpath?view=powershellsdk-1. 1
stackoverflow.com/questions/46308030/handling-path-too-long-exception-with-new-psdrive/46309524
luisabreu.wordpress.com/2013/02/15/theliteralpath-parameter 0
docs.microsoft.com/en-us/powershell/module/microsoft.powershell.management/get-childitem?view=powershell-5.

Теги
Показать больше

Похожие статьи

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Кнопка «Наверх»
Закрыть