Wie finde ich in Windows Dateien mit einer Pfadlänge von mehr als 260 Zeichen?

85

Ich verwende eine xcopy in einem XP-Windows-Skript, um ein Verzeichnis rekursiv zu kopieren. Ich erhalte immer wieder den Fehler "Unzureichender Speicher". Ich verstehe, dass eine Datei, die ich kopieren möchte, einen zu langen Pfad hat. Ich kann die Pfadlänge leicht reduzieren, aber leider kann ich nicht herausfinden, welche Dateien gegen die Pfadlängenbeschränkung verstoßen. Die kopierten Dateien werden in die Standardausgabe gedruckt (die ich in eine Protokolldatei umleitung), aber die Fehlermeldung wird auf dem Terminal gedruckt, sodass ich nicht einmal ungefähr herausfinden kann, für welches Verzeichnis der Fehler angegeben wird .

WestHamster
quelle

Antworten:

113

Machen Sie eine dir /s /b > out.txtund fügen Sie dann eine Führung an Position 260 hinzu

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

Wiederholung
quelle
1
dir / s / b> out.txt macht den Job wunderbar. Vielen Dank. "'Get-ChildItem' wird nicht als interner oder externer Befehl, bedienbares Programm oder Batchdatei erkannt." Ich glaube, ich habe keine Powershell.
WestHamster
1
@WestHamster, Sie müssen diesen Befehl in der PowerShell-Konsole ausführen.
Rami A.
6
Es wird ein Fehler wie folgt angezeigt: Außerdem 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.wird nur ein verkürzter Pfad gedruckt. zB : D:\Dropbox\ProY...sh._setbinddata. Das sind genau die Wege, die ich finden möchte, aber ich kann nicht den ganzen Weg sehen! Wie kann man das umgehen?
MiniGod
Bin ich der einzige, der das nicht zum Laufen bringen kann? Verwenden von Win7 64-Bit Home Premium, Powershell 2.0 - Wenn ich eine Testdatei mit einem langen Namen (240 Zeichen) erstelle und dann das Verzeichnis umbenenne, in dem sie sich befindet, um auch einen langen Namen zu haben, wird Get-ChildItems -r *die Datei nicht mehr angezeigt ... dir /s /bfunktioniert nur für mich.
Jonas Heidelberg
In meiner Antwort finden Sie eine Möglichkeit, dies in Powershell zu erreichen. So können Sie entweder die fehlerhaften Dateinamen (die über 260 Zeichen liegen) finden oder sie alternativ ignorieren.
Jonno
31

Zu diesem Zweck habe ich das Tool zur Überprüfung der Pfadlänge erstellt. Dies ist eine nette, kostenlose GUI-App, mit der Sie die Pfadlängen aller Dateien und Verzeichnisse in einem bestimmten Verzeichnis anzeigen können.

Ich habe auch über ein einfaches PowerShell-Skript zum Abrufen von Datei- und Verzeichnislängen geschrieben und gebloggt . Es gibt die Länge und den Pfad zu einer Datei aus und schreibt sie optional auch in die Konsole. Es beschränkt sich nicht nur auf die Anzeige von Dateien, die nur eine bestimmte Länge haben (eine einfache Änderung), sondern zeigt sie nach Länge absteigend an, sodass Sie immer noch sehr einfach erkennen können, welche Pfade über Ihrem Schwellenwert liegen. Hier ist es:

$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()
tödlicher Hund
quelle
2
Interessantes Skript, aber ich 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.
erhalte
Exzellentes Werkzeug !! Ich hatte ein riesiges Date und wollte ein Backup auf einer WD MyCloud HDD erstellen. Durch dieses Tool wurde die maximale Länge zum Erstellen einer Ordnerstruktur auf der Festplatte ermittelt. Vielen Dank.
NJMR
26

Als Verfeinerung der einfachsten Lösung und wenn Sie Powershell nicht installieren können oder wollen, führen Sie einfach Folgendes aus:

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

oder (schneller):

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

Und Zeilen, die länger als 260 sind, werden an die Spitze der Liste gesetzt. Beachten Sie, dass Sie dem Spaltenparameter SORT (/ + n) 1 hinzufügen müssen.

Chungalin
quelle
Danke für die Verfeinerung. Es war mein Fall, dass ich Powershell (Windows 2003 Box) nicht installieren konnte. ABGESTIMMT
20.
Können Sie erklären, warum Sie 1 genauer hinzufügen müssen?
Xonatron
Gibt es eine Möglichkeit, die Ausgabedatei nach Zeilenlänge zu sortieren?
Xonatron
5

Ich habe hier eine Alternative zu den anderen guten Antworten gemacht, die PowerShell verwenden, aber meine speichert die Liste auch in einer Datei. Ich werde es hier teilen, falls jemand anderes so etwas möchte.

Warnung: Code überschreibt "longfilepath.txt" im aktuellen Arbeitsverzeichnis. Ich weiß, es ist unwahrscheinlich, dass Sie bereits eine haben, aber nur für den Fall!

Wollte es absichtlich in einer einzigen Zeile:

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

Detaillierte Anleitung:

  1. Führen Sie PowerShell aus
  2. Wechseln Sie zu dem Verzeichnis, in dem Sie nach Dateipfadlängen suchen möchten (C: funktioniert).
  3. Kopieren Sie den Code und fügen Sie ihn ein. [Klicken Sie mit der rechten Maustaste, um ihn in PowerShell einzufügen, oder Alt + Leertaste> E> P]
  4. Warten Sie, bis es fertig ist, und zeigen Sie dann die Datei an: cat longfilepath.txt | sort

Erläuterung:

Out-File longfilepath.txt ;- Erstellen (oder überschreiben) Sie eine leere Datei mit dem Titel 'longfilepath.txt'. Semikolon zum Trennen von Befehlen.

cmd /c "dir /b /s /a" |- Führen Sie den Befehl dir in PowerShell aus, /aum alle Dateien einschließlich versteckter Dateien anzuzeigen. |zu pfeifen.

ForEach-Object { if ($_.length -gt 250) {$_ | Out-File -append longfilepath.txt}} - Wenn die Länge für jede Zeile (mit $ _ bezeichnet) größer als 250 ist, hängen Sie diese Zeile an die Datei an.

Rani Kheir
quelle
2

Sie können stderr umleiten.

Weitere Erklärungen hier , aber mit einem Befehl wie:

MyCommand >log.txt 2>errors.txt

sollte die Daten greifen, die Sie suchen.

Als Trick umgeht Windows diese Einschränkung, wenn dem Pfad \\?\( msdn ) vorangestellt wird.

Ein weiterer Trick, wenn Sie eine Wurzel oder ein Ziel haben, das mit einem langen Pfad beginnt, SUBSThilft vielleicht :

SUBST Q: "C:\Documents and Settings\MyLoginName\My Documents\MyStuffToBeCopied"
Xcopy Q:\ "d:\Where it needs to go" /s /e
SUBST Q: /D
SeanC
quelle
Das Umleiten der Standardausgabe und der Fehler sollte mir einen hinreichenden Hinweis darauf geben, wo sich die große Datei befindet. Befehl> Datei 2> & 1
WestHamster
das wird funktionieren, aber mein Befehl sollte die Fehler in eine separate Datei trennen
SeanC
\\? \ sieht auch gut aus. Ich kann jedoch Folgendes nicht zum Laufen bringen: xcopy / s \\? \ Q: \ nuthatch \\? \ Q: \
finch
hmm ... scheint \\?\ nicht für die Kommandozeile zu funktionieren. Eine weitere Idee mitSUBST
SeanC
Leider ist subst nicht allzu nützlich, da der Befehl vom Typ xcopy / sq: \ nuthatch q: \ finch <br/> ist und der lange Pfad an einer unter
nuthatch
2

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

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

Der erste Teil durchläuft nur diesen und die Unterordner. Mit -ErrorVariable AccessDeniedMitteln schieben Sie die beleidigenden Elemente in die Powershell-Variable AccessDenied.

Sie können dann die Variable wie folgt durchsuchen

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

Wenn Sie sich nicht für diese Dateien interessieren (kann in einigen Fällen zutreffen), lassen Sie das -ErrorVariable AccessDeniedTeil einfach fallen .

Jonno
quelle
Das Problem ist, dass $_.TargetObjectes nicht den vollständigen Pfad zu verletzenden Dateien enthält, sondern MAX_PATHnur Verzeichnisnamen und den übergeordneten Verzeichnisnamen der fehlerhaften Dateien. Ich arbeite daran, eine Nicht-Robocopy- oder Subst- oder Xcopy-Lösung zu finden, und werde sie veröffentlichen, wenn ich eine funktionierende Lösung finde.
user66001
-2

Für Pfade größer als 260:
Sie können verwenden:

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

Beispiel für 14 Zeichen:
So zeigen Sie die Pfadlängen an:

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

Erhalten Sie Pfade größer als 14:

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

Bildschirmfoto:
Geben Sie hier die Bildbeschreibung ein

Für Dateinamen größer als 10:

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

Bildschirmfoto:
Geben Sie hier die Bildbeschreibung ein

E235
quelle
4
Sie haben offensichtlich keine Ahnung von dem Problem. Nichts von dem, was Sie vorgeschlagen haben, funktioniert. Bitte lesen Sie
n0rd