Como encontro arquivos com um comprimento de caminho superior a 260 caracteres no Windows?


87

Estou usando um xcopy em um script do Windows XP para copiar recursivamente um diretório. Sempre recebo um erro de 'Memória insuficiente', que entendi ser porque um arquivo que estou tentando copiar tem um caminho muito longo. Posso reduzir facilmente o comprimento do caminho, mas infelizmente não consigo descobrir quais arquivos estão violando a restrição de comprimento do caminho. Os arquivos copiados são impressos na saída padrão (que estou redirecionando para um arquivo de log), mas a mensagem de erro é impressa no terminal, então não consigo nem descobrir aproximadamente para qual diretório o erro está sendo fornecido .


Respostas:


114

faça um dir /s /b > out.txte, em seguida, adicione um guia na posição 260

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


1
dir / s / b> out.txt faz o trabalho perfeitamente. Obrigado. "'Get-ChildItem' não é reconhecido como um comando interno ou externo, programa operável ou arquivo em lote." Acho que não tenho PowerShell.
WestHamster,

1
@WestHamster, você terá que executar esse comando no console do PowerShell.
Rami A.

6
Ele apresenta um erro como: 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.Junto com ele, apenas um caminho reduzido é impresso. por exemplo: D:\Dropbox\ProY...sh._setbinddata. Esses são exatamente os caminhos que quero encontrar, mas não consigo ver o caminho completo! Alguma maneira de contornar isso?
MiniGod

Eu sou o único que não consegue fazer isso funcionar? Usando Win7 64 bits Home Premium, Powershell 2.0 - quando eu crio um arquivo de teste com um nome longo (240 caracteres) e, em seguida, renomeio o diretório no qual ele se encontra para também ter um nome longo, Get-ChildItems -r *para de ver o arquivo ... só dir /s /bfunciona para mim.
Jonas Heidelberg

Veja minha resposta para uma maneira de fazer isso no PowerShell, permitindo que você encontre os nomes de arquivo ofensivos (aqueles acima de 260 caracteres) ou, alternativamente, ignore-os.
Jonno,

31

Eu criei a ferramenta Path Length Checker para esse propósito, que é um bom aplicativo GUI gratuito que você pode usar para ver os comprimentos de caminho de todos os arquivos e diretórios em um determinado diretório.

Também escrevi e bloguei sobre um script simples do PowerShell para obter tamanhos de arquivo e diretório. Ele irá mostrar o comprimento e o caminho para um arquivo e, opcionalmente, gravá-lo no console também. Ele não se limita a exibir arquivos que têm apenas um determinado comprimento (uma modificação fácil de fazer), mas os exibe em ordem decrescente de comprimento, então ainda é muito fácil ver quais caminhos estão acima do seu limite. Aqui está:

$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
Script interessante, mas ainda estou recebendo este erro: 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

Excelente ferramenta !! Eu tinha um grande encontro, queria criar um backup em um WD MyCloud HDD. Por esta ferramenta veio a saber o comprimento máximo para criar uma estrutura de pastas no HDD. Obrigado.
NJMR

27

Como um refinamento da solução mais simples, e se você não puder ou não quiser instalar o Powershell, basta executar:

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

ou (mais rápido):

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

E as linhas com mais de 260 chegarão ao topo da lista. Observe que você deve adicionar 1 ao parâmetro da coluna SORT (/ + n).


Obrigado pelo refinamento. No meu caso, não consegui instalar o Powershell (caixa do Windows 2003). VOTADO
etapa

Você pode explicar por que você tem que adicionar 1 em mais detalhes?
Xonatron

Existe uma maneira de classificar o arquivo de saída pelo comprimento da linha?
Xonatron

@Xonatron, "E linhas com mais de 260"
penhasco de

Votado. Eu acho que isso também deve mencionar SUBST para encurtar um caminho em um ftw de unidade.
precipício de

6

Fiz uma alternativa para as outras boas respostas aqui que usam PowerShell, mas a minha também salva a lista em um arquivo. Vou compartilhar aqui, caso alguém precise e queira algo assim.

Aviso: o código sobrescreve "longfilepath.txt" no diretório de trabalho atual. Eu sei que é improvável que você já tenha um, mas apenas no caso!

Desejado propositalmente em uma única linha:

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

Instruções detalhadas:

  1. Execute PowerShell
  2. Vá até o diretório em que deseja verificar os comprimentos do caminho de arquivo (C: funciona)
  3. Copie e cole o código [clique com o botão direito para colar no PowerShell ou Alt + Espaço> E> P]
  4. Espere até terminar e veja o arquivo: cat longfilepath.txt | sort

Explicação:

Out-File longfilepath.txt ;- Crie (ou substitua) um arquivo em branco intitulado 'longfilepath.txt'. Ponto-e-vírgula para separar comandos.

cmd /c "dir /b /s /a" |- Execute o comando dir no PowerShell, /apara mostrar todos os arquivos, incluindo arquivos ocultos. |para canalizar.

ForEach-Object { if ($_.length -gt 250) {$_ | Out-File -append longfilepath.txt}} - Para cada linha (denotada como $ _), se o comprimento for maior que 250, anexe essa linha ao arquivo.


2

você pode redirecionar stderr.

mais explicação aqui , mas com um comando como:

MyCommand >log.txt 2>errors.txt

deve obter os dados que você está procurando.

Além disso, como um truque, o Windows contorna essa limitação se o caminho for prefixado com \\?\( msdn )

Outro truque, se você tiver uma raiz ou destino que começa com um longo caminho, talvez SUBSTajude:

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

Redirecionar a saída std e os erros deve me dar uma indicação boa o suficiente de onde está o arquivo grande, obrigado. comando> arquivo 2> & 1
WestHamster

isso vai funcionar, mas meu comando deve separar os erros em um arquivo separado
SeanC

\\? \ também parece bom. Não consigo fazer o seguinte funcionar: xcopy / s \\? \ Q: \ nuthatch \\? \ Q: \ finch
WestHamster

hmm ... parece \\?\ que não funciona para a linha de comando. Adicionada outra ideia usandoSUBST
SeanC

Infelizmente subst não será muito útil porque o comando é do tipo: xcopy / sq: \ nuthatch q: \ finch <br/> e o caminho longo está embutido em algum lugar desconhecido sob nuthatch
WestHamster

2

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

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

a primeira parte apenas itera por meio desta e das subpastas; usar -ErrorVariable AccessDeniedsignifica empurrar os itens ofensivos para a variável powershell AccessDenied.

Você pode então percorrer a variável assim

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

Se você não se importa com esses arquivos (podem ser aplicáveis ​​em alguns casos), simplesmente descarte a -ErrorVariable AccessDeniedparte.


O problema é $_.TargetObjectque não contém o caminho completo para os arquivos violados MAX_PATH, apenas os nomes dos diretórios e o nome do diretório pai dos arquivos ofensivos. Estou trabalhando para encontrar uma solução que não seja Robocopy, Subst ou Xcopy e postarei quando encontrar uma solução que funcione.
user66001


-2

Para caminhos maiores que 260:
você pode usar:

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

Exemplo em 14 caracteres:
Para visualizar os comprimentos dos caminhos:

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

Obtenha caminhos maiores que 14:

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

Captura de tela:
insira a descrição da imagem aqui

Para nomes de arquivos maiores que 10:

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

Captura de tela:
insira a descrição da imagem aqui


4
Você obviamente não tem ideia do problema. Nada do que você sugeriu funciona. Por favor, leia
n0rd
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.