Я использую xcopy в Windows XP script, чтобы рекурсивно скопировать каталог. Я продолжаю получать ошибку "Недостаточно памяти", которая, как я понимаю, связана с тем, что файл, который я пытаюсь скопировать, имеет слишком длинный путь. Я могу легко уменьшить длину пути, но, к сожалению, я не могу решить, какие файлы нарушают ограничение длины пути. Скопированные файлы печатаются на стандартный вывод (который я перенаправляю в файл журнала), но сообщение об ошибке печатается на терминале, поэтому я даже не могу определить, в какой директории это ошибка.
Как найти файлы с длиной пути, превышающей 260 символов в Windows?
Ответ 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}
Скриншот:
Для имен файлов больше 10:
Get-ChildItem | Where-Object {$_.PSChildName.Length -gt 10}
Скриншот: