Как найти файлы с длиной пути более 260 символов в Windows?

Я использую xcopy в скрипте Windows XP для рекурсивного копирования каталога. Я продолжаю получать ошибку "недостаточно памяти", которую я понимаю, потому что файл, который я пытаюсь скопировать, имеет слишком длинный путь. Я могу легко уменьшить длину пути, но, к сожалению, я не могу понять, какие файлы нарушают ограничение длины пути. Скопированные файлы печатаются на стандартный вывод (который я перенаправляю в файл журнала), но сообщение об ошибке печатается на терминал, поэтому я не может даже приблизительно определить, для какого каталога выдается ошибка.

8 ответов


сделать dir /s /b > out.txt а затем добавьте направляющую в положение 260

в powershell cmd /c dir /s /b |? {$_.length -gt 260}


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

У меня тоже написано и опубликовано в блоге о простом сценарии PowerShell для получения длины файлов и каталогов. Он выведет длину и путь к файлу и, возможно, запишет его на консоль. Это не ограничивает отображение файлов, которые находятся только над a определенная длина (простая модификация), но отображает их по длине, поэтому все еще очень легко увидеть, какие пути находятся за вашим порогом. Вот это:

$pathToScan = "C:\Some Folder"  # The path to scan and the the lengths for (sub-directories will be scanned as well).
$outputFilePath = "C:\temp\PathLengths.txt" # This must be a file in a directory that exists and does not require admin rights to write to.
$writeToConsoleAsWell = $true   # Writing to the console will be much slower.

# Open a new file stream (nice and fast) and write all the paths and their lengths to it.
$outputFileDirectory = Split-Path $outputFilePath -Parent
if (!(Test-Path $outputFileDirectory)) { New-Item $outputFileDirectory -ItemType Directory }
$stream = New-Object System.IO.StreamWriter($outputFilePath, $false)
Get-ChildItem -Path $pathToScan -Recurse -Force | Select-Object -Property FullName, @{Name="FullNameLength";Expression={($_.FullName.Length)}} | Sort-Object -Property FullNameLength -Descending | ForEach-Object {
    $filePath = $_.FullName
    $length = $_.FullNameLength
    $string = "$length : $filePath"

    # Write to the Console.
    if ($writeToConsoleAsWell) { Write-Host $string }

    #Write to the file.
    $stream.WriteLine($string)
}
$stream.Close()

как уточнение простейшего решения, и если вы не можете или не хотите устанавливать Powershell, просто запустите:

dir /s /b | sort /r /+261 > out.txt

или (быстрее):

dir /s /b | sort /r /+261 /o out.txt

и строки длиннее 260 попадут в начало списка. Обратите внимание, что для сортировки параметра столбца (/+n) необходимо добавить 1.


вы можете перенаправить stderr.

больше объяснений здесь, но имея команду, как:

MyCommand >log.txt 2>errors.txt

должны захватить данные, которые вы ищете.

кроме того, как трюк, Windows обходит это ограничение, если путь имеет префикс \?\ (в MSDN)

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

SUBST Q: "C:\Documents and Settings\MyLoginName\My Documents\MyStuffToBeCopied"
Xcopy Q:\ "d:\Where it needs to go" /s /e
SUBST Q: /D

от http://www.powershellmagazine.com/2012/07/24/jaap-brassers-favorite-powershell-tips-and-tricks/:

Get-ChildItem –Force –Recurse –ErrorAction SilentlyContinue –ErrorVariable AccessDenied

первая часть просто повторяет это и подпапки; используя -ErrorVariable AccessDenied означает, что вытолкните оскорбительные элементы в переменную powershell AccessDenied.

затем вы можете сканировать переменную так

$AccessDenied |
Where-Object { $_.Exception -match "must be less than 260 characters" } |
ForEach-Object { $_.TargetObject }

если вы не заботитесь об этих файлах (может быть применимо в некоторых случаях), просто удалить -ErrorVariable AccessDenied часть.


Я сделал альтернативу другим хорошим ответам здесь, который использует PowerShell, но мой также сохраняет список в файл. Поделюсь здесь на случай, если кому-то еще понадобится что-то подобное.

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

нарочно хотел его в одну строку:

Out-File longfilepath.txt ; cmd /c "dir /b /s /a" | ForEach-Object { if ($_.length -gt 250) {$_ | Out-File -append longfilepath.txt}}

подробно инструкции:

  1. Запустить PowerShell
  2. перейдите в каталог, который вы хотите проверить на длину пути к файлу (C: works)
  3. скопируйте и вставьте код [щелкните правой кнопкой мыши, чтобы вставить в PowerShell, или Alt + Space > E > P]
  4. подождите, пока это не будет сделано, а затем просмотрите файл:cat longfilepath.txt | sort

объяснение:

Out-File longfilepath.txt ; - создать (или перезаписать) пустой файл под названием 'longfilepath.txt'. Двоеточие к отдельная команда.

cmd /c "dir /b /s /a" | – запустите команду dir в PowerShell,/a показать все файлы, включая скрытые файлы. | в трубу.

ForEach-Object { if ($_.length -gt 250) {$_ | Out-File -append longfilepath.txt}} – для каждой строки (обозначенной как $_), если длина больше 250, добавьте эту строку в файл.


TLPD ("too long path directory") - это программа, которая спасла меня. Очень проста в использовании:

https://sourceforge.net/projects/tlpd/


для путей более 260:
вы можете использовать:

Get-ChildItem | Where-Object {$_.FullName.Length -gt 260}

пример на 14 символов:
Для просмотра длины путей:

Get-ChildItem | Select-Object -Property FullName, @{Name="FullNameLength";Expression={($_.FullName.Length)}

получить пути больше, чем 14:

Get-ChildItem | Where-Object {$_.FullName.Length -gt 14}  

скриншоты:
enter image description here

для имен файлов больше 10:

Get-ChildItem | Where-Object {$_.PSChildName.Length -gt 10}

скриншоты:
enter image description here