Comment puis-je trouver des fichiers avec une longueur de chemin supérieure à 260 caractères dans Windows?
J'utilise un xcopy dans un script windows XP pour copier récursivement un répertoire. Je continue à avoir une erreur "Mémoire insuffisante", ce que je comprends parce qu'un fichier que j'essaie de copier a un chemin trop long. Je peux facilement réduire la longueur du chemin, mais malheureusement, je ne peux pas déterminer quels fichiers violent la restriction de longueur de chemin. Les fichiers copiés sont imprimés sur la sortie standard (que je redirige vers un fichier journal), mais le message d'erreur est imprimé sur le terminal, donc je ne peux pas même déterminer approximativement le répertoire pour lequel l'erreur est donnée.
8 réponses
Faites un dir /s /b > out.txt
puis ajoutez un guide à la position 260
Dans powershell cmd /c dir /s /b |? {$_.length -gt 260}
J'ai créé L'outil de vérification de la longueur du chemin à cet effet, qui est une belle application graphique gratuite que vous pouvez utiliser pour voir les longueurs de chemin de tous les fichiers et répertoires dans un répertoire donné.
J'ai aussi écrit et blogué sur un script PowerShell simple pour obtenir des longueurs de fichiers et de répertoires. Il produira de la longueur et le chemin d'accès à un fichier, et éventuellement l'écrire dans la console. Il ne se limite pas à afficher des fichiers qui ne sont que sur une certaine longueur (un facile modification à faire), mais les affiche en descendant par longueur, il est donc toujours super facile de voir quels chemins sont au-dessus de votre seuil. Ici, il 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()
Comme un raffinement de la solution la plus simple, et si vous ne pouvez pas ou ne voulez pas installer Powershell, exécutez simplement:
dir /s /b | sort /r /+261 > out.txt
Ou (plus rapide):
dir /s /b | sort /r /+261 /o out.txt
Et les lignes de plus de 260 arriveront en haut de la liste. Notez que vous devez ajouter 1 au paramètre de colonne de tri (/+n).
Vous pouvez rediriger stderr.
Plus d'explication ici , mais ayant une commande comme:
MyCommand >log.txt 2>errors.txt
Devrait saisir les données que vous recherchez.
Aussi, comme une astuce, Windows contourne cette limitation si le chemin est préfixé avec \\?\
(msdn)
Une Autre astuce si vous avez une racine ou une destination qui commence par un long chemin, peut-être SUBST
aidera:
SUBST Q: "C:\Documents and Settings\MyLoginName\My Documents\MyStuffToBeCopied"
Xcopy Q:\ "d:\Where it needs to go" /s /e
SUBST Q: /D
Depuis http://www.powershellmagazine.com/2012/07/24/jaap-brassers-favorite-powershell-tips-and-tricks/:
Get-ChildItem –Force –Recurse –ErrorAction SilentlyContinue –ErrorVariable AccessDenied
La première partie parcourt simplement ceci et les sous-dossiers; utiliser -ErrorVariable AccessDenied
signifie pousser les éléments incriminés dans la variable powershell AccessDenied
.
Vous pouvez ensuite parcourir la variable comme ceci
$AccessDenied |
Where-Object { $_.Exception -match "must be less than 260 characters" } |
ForEach-Object { $_.TargetObject }
Si vous ne vous souciez pas de ces fichiers (peut être applicable dans certains cas), supprimez simplement la partie -ErrorVariable AccessDenied
.
J'ai fait une alternative aux autres bonnes réponses ici qui utilise PowerShell, mais le mien enregistre également la liste dans un fichier. Partagez ici au cas où quelqu'un d'autre a besoin veut quelque chose comme ça.
Avertissement: le Code écrase " longfilepath.txt " dans le répertoire de travail actuel. Je sais qu'il est peu probable que vous en ayez déjà un, mais juste au cas où!
Délibérément voulu en une seule ligne:
Out-File longfilepath.txt ; cmd /c "dir /b /s /a" | ForEach-Object { if ($_.length -gt 250) {$_ | Out-File -append longfilepath.txt}}
Des instructions Détaillées:
- exécuter PowerShell
- parcourez le répertoire que vous voulez vérifier pour les longueurs de chemin de fichier (c: works)
- copiez et collez le code [clic droit pour coller dans PowerShell, ou Alt + Espace > E > P]
- attendez que ce soit fait, puis affichez le fichier:
cat longfilepath.txt | sort
Explication:
Out-File longfilepath.txt ;
– Créez (ou écrasez) un fichier vide intitulé 'longfilepath.txt". Point-virgule pour séparer les commandes.
cmd /c "dir /b /s /a" |
– Exécutez la commande dir sur PowerShell, /a
pour afficher tous les fichiers y compris les fichiers cachés. {[5] } à pipe.
ForEach-Object { if ($_.length -gt 250) {$_ | Out-File -append longfilepath.txt}}
– pour chaque ligne (notée$_), si la longueur est supérieure à 250, Ajoutez cette ligne au fichier.
TLPD ("répertoire de chemin trop long") est le programme qui m'a sauvé. Très facile à utiliser:
Pour les chemins supérieurs à 260:
vous pouvez utiliser:
Get-ChildItem | Where-Object {$_.FullName.Length -gt 260}
Exemple sur 14 caractères:
Pour afficher les longueurs des chemins:
Get-ChildItem | Select-Object -Property FullName, @{Name="FullNameLength";Expression={($_.FullName.Length)}
Obtenir des chemins supérieurs à 14:
Get-ChildItem | Where-Object {$_.FullName.Length -gt 14}
Capture d'écran:
Pour les noms de fichiers supérieurs à 10:
Get-ChildItem | Where-Object {$_.PSChildName.Length -gt 10}
Capture d'écran: