Компьютер, на котором я запускаю скрипт, - это PS5, но это очень маловероятно на машинах, на которых размещена общая папка. Моя следующая попытка возвращает ошибку: Недопустимые символы в пути. Get-ChildItem -LiteralPath "\\? \ UNC \ somesever \ myshare $ \ folder1 \ folder2 \ folder3" -Recurse -Directory

ользую глубокую структуру папок, чтобы получить все пути к папкам, например:

$subFolders = Get-ChildItem $rootFolder -Recurse -Directory  -ErrorVariable folderErrors | Select-Object -ExpandProperty FullName

ПРИМЕЧАНИЕ: $ rootFolder в моем случае является сетевым ресурсом. Т.е. "\\ server \ DeptDir $ \ somefolder"

$folderErrors переменная корректно фиксирует все исключения FileTooLong, поэтому я хочу создать новые PSDrive, используя длинные пути, чтобы рекурсировать эти длинные пути.

Поэтому я создаю новый PSDrive с помощью этого командлета:

new-psdrive -Name "long1" -PSProvider FileSystem -Root $folderErrors[0].CategoryInfo.TargetName

Однако после создания нового PSDrive я все еще получаю исключения PathTooLong.

PS C:\>> cd long1:
PS long1:\>> dir
dir : 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.
At line:1 char:1
+ dir
+ ~~~
    + CategoryInfo          : ReadError: (\\svr01\Dep...\Fibrebond ECO\:String) [Get-ChildItem], PathTooLongException
    + FullyQualifiedErrorId : DirIOError,Microsoft.PowerShell.Commands.GetChildItemCommand

Я не вижу другого пути решения этой проблемы. Я что-то делаю неправильно? Почему новый PSDrive выбрасывает PathTooLong, когда я создаю диск в месте, где путь слишком длинный?

Спасибо

 PetSerAl19 сент. 2017 г., 22:32
использованиеsubst вместоNew-PSDrive.

Ответы на вопрос(1)

Решение Вопроса

которая теперь доступна после годовщины обновления Windows.

Требования:

Windows Management Framework 5.1

.Net Framework 4.6.2 или более поздняя версия

Windows 10 / Windows server 2016 (сборка 1607 или новее)

Эта политика может быть включена с использованием следующего фрагмента.

#GPEdit location:  Configuration>Administrative Templates>System>FileSystem 
Set-ItemProperty 'HKLM:\System\CurrentControlSet\Control\FileSystem' -Name 'LongPathsEnabled' -value 1

В противном случае вы можете перейти к путям длиннее 260 символов, позвонив в Unicode-версии Windows API.

Хотя есть подвох. Эта работа только вPowershell 5.1 минимум.

Оттуда вместо того, чтобы сделать ваш звонок стандартным способом:

get-childitem -Path 'C:\Very long path' -Recurse  

Вам нужно будет использовать следующий префикс:\\?\

пример

get-childitem -LiteralPath '\\?\C:\Very long path' -Recurse 

Для пути UNC это немного отличается, префикс\\?\UNC\ вместо\\

get-childitem -LiteralPath '\\?\UNC\127.0.0.1\c$\Very long path\' -Recurse

Важный

При звонкеGet-ChildItem версия Unicode, вы должны использовать-LiteralPath параметр вместоPath

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

-LiteralPath

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

источник

пример

(get-childitem -LiteralPath '\\?\UNC\127.0.0.1\This is a folder

выход

Вот фактический функциональный тест, который я сделал, чтобы создать очень длинный репозиторий, запросить его, чтобы получить приведенный выше вывод, и подтвердить, что я могу создать репозиторий с более чем 260 символами и просматривать их.

Function CreateVeryLongPath([String]$Root,[Switch]$IsUNC,$FolderName = 'Dummy Folder',$iterations = 200) {
    $Base = '\\?\'
    if ($IsUNC) {$Base = '\\?\UNC\'}

    $CurrentPath = $Base + $Root + $FolderName + '\'

    For ($i=0;$i -le $iterations;$i++) {

    New-Item -Path $CurrentPath -Force -ItemType Directory | Out-Null
    $currentPath = $CurrentPath +  $FolderName + '\'
    }
}

Function QueryVeryLongPath([String]$Root,[Switch]$IsUNC) {
    $Base = '\\?\'
    if ($IsUNC) {$Base = '\\?\UNC\';$Root = $Root.substring(2,$Root.Length -2)}

    $BasePath = $Base + $Root
    Get-ChildItem -LiteralPath $BasePath -Recurse | ft @{'n'='Length';'e'={$_.FullName.Length}},FullName
}



CreateVeryLongPath -Root 'C:\__tmp\' -FolderName 'This is a folder'
QueryVeryLongPath -Root 'C:\__tmp\Dummy Folder11\' 

#UNC - tested on a UNC share path 
CreateVeryLongPath -Root '\\ServerName\ShareName\' -FolderName 'This is a folder' -IsUNC
QueryVeryLongPath -Root '\\ServerName\ShareName\' -IsUNC

Стоит упомянуть

Во время моего исследования я видел, как люди упоминают об использовании RoboCopy, а затем анализируют его результаты. Я не особенно люблю этот подход, поэтому я не буду останавливаться на нем.

Я тоже виделAlphaFS упомянутое пару раз, это библиотека, которая позволяет преодолеть ограничение в 260 символов. Он открыт на Github и даже есть (хотя я его не тестировал)Get-AlphaFSChildItem построен на нем доступны на TechnetВот

Другие ссылки

Длинные пути в .Net

Именование файлов, путей и пространств имен

-Recurse) | ft @{'n'='Path length';'e'={$_.FullName.length}}, FullName

выход

Вот фактический функциональный тест, который я сделал, чтобы создать очень длинный репозиторий, запросить его, чтобы получить приведенный выше вывод, и подтвердить, что я могу создать репозиторий с более чем 260 символами и просматривать их.

Function CreateVeryLongPath([String]$Root,[Switch]$IsUNC,$FolderName = 'Dummy Folder',$iterations = 200) {
    $Base = '\\?\'
    if ($IsUNC) {$Base = '\\?\UNC\'}

    $CurrentPath = $Base + $Root + $FolderName + '\'

    For ($i=0;$i -le $iterations;$i++) {

    New-Item -Path $CurrentPath -Force -ItemType Directory | Out-Null
    $currentPath = $CurrentPath +  $FolderName + '\'
    }
}

Function QueryVeryLongPath([String]$Root,[Switch]$IsUNC) {
    $Base = '\\?\'
    if ($IsUNC) {$Base = '\\?\UNC\';$Root = $Root.substring(2,$Root.Length -2)}

    $BasePath = $Base + $Root
    Get-ChildItem -LiteralPath $BasePath -Recurse | ft @{'n'='Length';'e'={$_.FullName.Length}},FullName
}



CreateVeryLongPath -Root 'C:\__tmp\' -FolderName 'This is a folder'
QueryVeryLongPath -Root 'C:\__tmp\Dummy Folder11\' 

#UNC - tested on a UNC share path 
CreateVeryLongPath -Root '\\ServerName\ShareName\' -FolderName 'This is a folder' -IsUNC
QueryVeryLongPath -Root '\\ServerName\ShareName\' -IsUNC

Стоит упомянуть

Во время моего исследования я видел, как люди упоминают об использовании RoboCopy, а затем анализируют его результаты. Я не особенно люблю этот подход, поэтому я не буду останавливаться на нем.

Я тоже виделAlphaFS упомянутое пару раз, это библиотека, которая позволяет преодолеть ограничение в 260 символов. Он открыт на Github и даже есть (хотя я его не тестировал)Get-AlphaFSChildItem построен на нем доступны на TechnetВот

Другие ссылки

Длинные пути в .Net

Именование файлов, путей и пространств имен

 Sage Pourpre20 сент. 2017 г., 21:52
У вас есть powershell 5? Я заметил, что это не работает на машинах PS4. Кроме того, у меня возникла та же проблема, что и у вас, когда я попробовал поделиться вместо Drive $. Чтобы исправить это, я использовал LiteralPath вместо Path. Я обновил свой ответ снова.
 ChiliYago20 сент. 2017 г., 23:26
Компьютер, на котором я запускаю скрипт, - это PS5, но это очень маловероятно на машинах, на которых размещена общая папка. Моя следующая попытка возвращает ошибку: Недопустимые символы в пути. Get-ChildItem -LiteralPath "\\? \ UNC \ somesever \ myshare $ \ folder1 \ folder2 \ folder3" -Recurse -Directory
 ChiliYago20 сент. 2017 г., 20:32
Я все еще ничего не получаю. Это моя попытка: Get-ChildItem "\\? \ UNC \ somesever \ myshare $ \ folder1 \ folder2 \ folder3" -Recurse -Directory
 ChiliYago20 сент. 2017 г., 00:11
Это выглядит многообещающе, но нет ... не работает .. ничего не вернулось. Я должен был заявить, что это сетевой ресурс. Таким образом, использование вашего примера в моем случае будет выглядеть так: Get-ChildItem -Path "\\? \ Server \ DeptDirs $ \ SomeFolder" -Recurse -Directory
 Sage Pourpre20 сент. 2017 г., 03:18
@ChiliYago На самом деле, для UNC префикс идет от \\? \ До \\? \ UNC \ YourServer. Смотрите последний пример в моем редактировании.

Ваш ответ на вопрос