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

Моя цель - предложение широкого ассортимента товаров и услуг на постоянно высоком качестве обслуживания по самым выгодным ценам.


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

Вот лишь некоторые из печальных последствий ограничения длины файлового пути:
  • на сервере есть папка, например, D:\Data\Shared\Accounting, которая расшарена по SMB и монтируется пользователям как сетевой диск S; пользователи создают файлы, которые не смогут прочитать админы/скрипты при локальном доступе с сервера, т.к. абсолютный путь получается длиннее сетевого;
  • ошибки синхронизации перемещаемых профилей;
  • проблемы с восстановлением из теневых копий;
  • при миграции данных с из других систем, в которых менее жёсткие ограничения к длине пути, в новом окружении часть из них станет недоступной без танцев с бубном;
  • неверные данные при подсчете размеров и количества файлов в папках;
  • etc...


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

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


Перейти на 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, политик, скриптов и эникеев других средств автоматизации.

Текущую версию PowerShell можно узнать из переменной $PSVersionTable. После обновления должно быть примерно так:

Теперь при использовании командлетов Get-ChildItem и ему подобных вместо привычного Path будем использовать LiteralPath.
Формат путей при этом будет немного другим:
Get-ChildItem -LiteralPath "\\?\C:\Folder"
Get-ChildItem -LiteralPath "\\?\UNC\ServerName\Share"
Get-ChildItem -LiteralPath "\\?\UNC\192.168.0.10\Share"


Для удобства преобразования путей из привычного формата в формат LiteralPath можно использовать вот такую функцию:
Function ConvertTo-LiteralPath {
Param([parameter(Mandatory=$true, Position=0)][String]$Path)
If ($Path.Substring(0,2) -eq "\\") {Return ("\\?\UNC" + $Path.Remove(0,1))}
Else {Return "\\?\$Path"}
}


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

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

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


Интересные статьи

Интересные статьи

В 2020 Covid-19 сделал онлайн-продажи ещё популярнее и ускорил выход магазинов в онлайн. Мировой объём розничных онлайн-продаж составил 3,53 триллиона долларов США в 2019...
Приветствую вас (лично вас, а не всех кто это читает)! Сегодня мы: Создадим приложение (навык) Алисы с использованием нового (октябрь 2019) сервиса Yandex Cloud Functions. Настроим н...
Хочу рассказать об одном из своих интересов – оптической голографии. Нет, это про не те голограммы, что в «Звёздных войнах», или в пирамидках на экранах мобильных телефонов, не про проекцию на пл...
Некоторое время назад мне довелось пройти больше десятка собеседований на позицию php-программиста (битрикс). К удивлению, требования в различных организациях отличаются совсем незначительно и...
Один из самых острых вопросов при разработке на Битрикс - это миграции базы данных. Какие же способы облегчить эту задачу есть на данный момент?