Как найти файлы с длиной пути, превышающей 260 символов в Windows?

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

Ответ 1

сделайте a dir /s /b > out.txt, а затем добавьте руководство в положение 260

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

Ответ 2

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

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

$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()

Ответ 3

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

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

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

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

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

Ответ 4

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

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

Целенаправленно хотелось в одной строке:

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

Подробные инструкции:

  • Запустить PowerShell
  • Перейдите в каталог, который вы хотите проверить на длину пути к файлу (C: works)
  • Скопируйте и вставьте код [Щелкните правой кнопкой мыши для вставки в PowerShell или Alt + Space > E > P]
  • Подождите, пока он не будет выполнен, а затем просмотрите файл: 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, добавьте эту строку в файл.

Ответ 5

вы можете перенаправить 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

Ответ 6

Из 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.

Ответ 7

Для путей больше 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