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

87

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

WestHamster
источник

Ответы:

114

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

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

повторить
источник
1
dir / s / b> out.txt прекрасно справляется со своей задачей. Спасибо. «Get-ChildItem не распознается как внутренняя или внешняя команда, работающая программа или командный файл». Полагаю, у меня нет PowerShell.
WestHamster
1
@WestHamster, вам нужно будет запустить эту команду в консоли PowerShell.
Рами А.
6
Выдает ошибку типа: Get-ChildItem : 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.Вместе с этим печатается только сокращенный путь. например: D:\Dropbox\ProY...sh._setbinddata. Это именно те пути, которые я хочу найти, но не могу увидеть весь путь! Как обойти это?
MiniGod
Я единственный, кто не может заставить это работать? Используя Win7 64 bit Home Premium, Powershell 2.0 - когда я создаю тестовый файл с длинным именем (240 символов), а затем переименовываю каталог, в котором он находится, также имеет длинное имя, Get-ChildItems -r *перестает видеть файл ... dir /s /bработает только для меня.
Йонас Гейдельберг,
См. Мой ответ, чтобы узнать, как добиться этого в PowerShell, позволяя вам либо находить неправильные имена файлов (те, которые превышают 260 символов), либо игнорировать их.
Джонно
31

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

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

$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()
смертоносная собака
источник
2
Интересный сценарий, но я все еще получаю эту ошибку: Get-ChildItem : 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.
zkurtz 04
Отличный инструмент !! У меня была огромная дата, я хотел создать резервную копию на жестком диске WD MyCloud. С помощью этого инструмента была определена максимальная длина для создания структуры папок на жестком диске. Спасибо.
NJMR
27

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

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

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

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

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

Чунгалин
источник
Спасибо за доработку. В моем случае я не смог установить Powershell (Windows 2003). ГОЛОСОВАНИЕ
preOtep
Вы можете более подробно объяснить, почему вам нужно добавить 1?
Xonatron 08
Есть ли способ отсортировать выходной файл по длине строки?
Xonatron 08
@Xonatron, "И строки длиннее 260"
cliffclof
Проголосовал за. Я думаю, здесь также следует упомянуть SUBST, чтобы сократить путь к диску ftw.
cliffclof
6

Я сделал альтернативу другим хорошим ответам здесь, в которых используется 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: работает)
  3. Скопируйте и вставьте код [щелкните правой кнопкой мыши, чтобы вставить в PowerShell, или Alt + Пробел> 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, добавьте эту строку в файл.

Рани Хейр
источник
2

вы можете перенаправить 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
SeanC
источник
Перенаправление вывода std и ошибок должно дать мне достаточно хорошее представление о том, где находится большой файл. команда> файл 2> & 1
WestHamster 03
это будет работать, но моя команда должна выделить ошибки в отдельный файл
SeanC 03
\\? \ тоже неплохо выглядит. Я не могу заставить работать следующее: xcopy / s \\? \ Q: \ nuthatch \\? \ Q: \
finch
хм ... похоже \\?\ , не работает в командной строке. Добавлена ​​еще одна идея с использованиемSUBST
SeanC 03
К сожалению, subst не будет слишком полезен, потому что команда имеет тип: xcopy / sq: \ nuthatch q: \ finch <br/>, а длинный путь встроен где-то неизвестно под поползнем
WestHamster 03
2

С 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часть.

Йонно
источник
Проблема в том, $_.TargetObjectчто не содержит полный путь к файлам, которые нарушают MAX_PATH, только имена каталогов и имя родительского каталога файлов-нарушителей. Я работаю над поиском решения, отличного от Robocopy, Subst или Xcopy, и опубликую, когда найду рабочее решение.
user66001
-2

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

Снимок экрана:
введите описание изображения здесь

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

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

Снимок экрана:
введите описание изображения здесь

E235
источник
4
Вы, очевидно, не имеете ни малейшего представления о проблеме. Ничего из того, что вы предложили, не работает. Пожалуйста, прочтите
n0rd