it-swarm.com.de

Löschen Sie das Verzeichnis unabhängig von der maximal zulässigen Länge von 260 Zeichen

Ich schreibe ein einfaches Skript, um USMT-Migrationsordner nach einer bestimmten Anzahl von Tagen zu löschen:

## Server List ##
$servers = "Delorean","Adelaide","Brisbane","Melbourne","Newcastle","Perth"

## Number of days (-3 is over three days ago) ##
$days = -3

$timelimit = (Get-Date).AddDays($days)

foreach ($server in $servers)
{
    $deletedusers = @()
    $folders = Get-ChildItem \\$server\USMT$ | where {$_.psiscontainer}
    write-Host "Checking server : " $server
    foreach ($folder in $folders) 
    {
        If ($folder.LastWriteTime -lt $timelimit -And $folder -ne $null)
        {
            $deletedusers += $folder
            Remove-Item -recurse -force $folder.fullname
        }
    }
        write-Host "Users deleted : " $deletedusers
        write-Host
}

Trotzdem schlage ich weiter auf das gefürchtete Remove-Item : 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.

Ich habe nach Problemumgehungen und Alternativen gesucht, aber sie drehen sich alle darum, dass es mir egal ist, was sich in dem Ordner befindet.

Ich habe auf eine einfachere Lösung gehofft, da mir der Ordnerinhalt nicht wirklich wichtig ist, wenn er zum Löschen markiert ist.

Gibt es ein anderes natives Powershell-Cmdlet als Remove-Item -recurse, mit dem ich mein Ziel erreichen kann?

43
mhouston100

Dies ist eine bekannte Einschränkung von PowerShell. Die Umgehung besteht darin, dir cmd zu verwenden (sorry, aber das ist wahr).

http://asysadmin.tumblr.com/post/17654309496/powershell-path-length-limitation

oder wie von AaronH erwähnt Antwort Verwenden Sie in diesem Beispiel die Syntax \? \, um Builds zu löschen

dir -Include build -Depth 1 | Remove-Item -Recurse -Path "\\?\$($_.FullName)"
9
Bill

Ich habe oft dieses Problem mit Knotenprojekten. Sie verschachteln ihre Abhängigkeiten und wenn sie einmal geklont sind, ist es schwierig, sie zu löschen. Ein Nizza Node Utility, auf das ich gestoßen bin, ist rimraf .

npm install rimraf -g
rimraf <dir>
54
Andy

Genau wie CADII in einer anderen Antwort gesagt hat: Robocopy kann Pfade erstellen, die länger als 260 Zeichen sind. Robocopy kann solche Pfade auch löschen. Sie können einfach einen leeren Ordner mit zu langen Namen über Ihren Pfad spiegeln, falls Sie ihn löschen möchten.

Beispielsweise:

robocopy C:\temp\some_empty_dir E:\temp\dir_containing_very_deep_structures /MIR

Hier ist die Robocopy-Referenz , um die Parameter und die verschiedenen Optionen zu kennen.

37
Harald

Diese Antwort auf SuperUser hat es für mich gelöst: https://superuser.com/a/274224/85532

Cmd /C "rmdir /S /Q $myDir"
22
Daniel Lee

Ich habe eine PowerShell-Funktion erstellt, die in der Lage ist, einen langen Pfad (> 260) mithilfe der genannten Robokopietechnik zu löschen :

function Remove-PathToLongDirectory 
{
    Param(
        [string]$directory
    )

    # create a temporary (empty) directory
    $parent = [System.IO.Path]::GetTempPath()
    [string] $name = [System.Guid]::NewGuid()
    $tempDirectory = New-Item -ItemType Directory -Path (Join-Path $parent $name)

    robocopy /MIR $tempDirectory.FullName $directory | out-null
    Remove-Item $directory -Force | out-null
    Remove-Item $tempDirectory -Force | out-null
}

Anwendungsbeispiel:

Remove-PathToLongDirectory c:\yourlongPath
15
Martin Brandl

Ich habe vor einiger Zeit einen Trick gelernt, mit dem sich Probleme mit langen Dateipfaden häufig umgehen lassen. Anscheinend fließen bei Verwendung einiger Windows-APIs bestimmte Funktionen durch Legacy-Code, der keine langen Dateinamen verarbeiten kann. Wenn Sie Ihre Pfade jedoch auf eine bestimmte Weise formatieren, wird der Legacy-Code vermieden. Der Trick, der dieses Problem löst, besteht darin, Pfade mit dem Präfix "\\? \" Zu referenzieren. Es sollte beachtet werden, dass nicht alle APIs dies unterstützen, aber in diesem speziellen Fall hat es für mich funktioniert, siehe mein Beispiel unten:

Das folgende Beispiel schlägt fehl:

PS D:\> get-childitem -path "D:\System Volume Information\dfsr" -hidden


Directory: D:\System Volume Information\dfsr


Mode                LastWriteTime     Length Name
----                -------------     ------ ----
-a-hs        10/09/2014  11:10 PM     834424 FileIDTable_2
-a-hs        10/09/2014   8:43 PM    3211264 SimilarityTable_2

PS D:\> Remove-Item -Path "D:\System Volume Information\dfsr" -recurse -force
Remove-Item : 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.
At line:1 char:1
+ Remove-Item -Path "D:\System Volume Information\dfsr" -recurse -force
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo          : WriteError: (D:\System Volume Information\dfsr:String) [Remove-Item], PathTooLongExcepti
on
+ FullyQualifiedErrorId : RemoveItemIOError,Microsoft.PowerShell.Commands.RemoveItemCommand

PS D:\>

Wenn Sie dem Pfad jedoch "\\? \" Voranstellen, funktioniert der Befehl erfolgreich:

PS D:\> Remove-Item -Path "\\?\D:\System Volume Information\dfsr" -recurse -force
PS D:\> get-childitem -path "D:\System Volume Information\dfsr" -hidden
PS D:\>
11
AaronH

Wenn Sie Ruby installiert haben, können Sie Fileman verwenden:

gem install fileman

Nach der Installation können Sie in Ihrer Eingabeaufforderung einfach Folgendes ausführen:

fm rm your_folder_path

Dieses Problem ist ein echtes Problem, wenn Sie in node.js unter Windows entwickeln. Daher ist es für Dateimanager sehr praktisch, von Zeit zu Zeit den gesamten Müll zu löschen

10
Nicolas Dao

Wenn Sie nur die Dateien löschen, verwende ich eine Funktion, um die Namen zu verkürzen, und lösche sie dann.

    function ConvertTo-ShortNames{
    param ([string]$folder)
    $name = 1
    $items = Get-ChildItem -path $folder
    foreach ($item in $items){
        Rename-Item -Path $item.FullName -NewName "$name"
        if ($item.PSIsContainer){
            $parts = $item.FullName.Split("\")
            $folderPath = $parts[0]
            for ($i = 1; $i -lt $parts.Count - 1; $i++){
                $folderPath = $folderPath + "\" + $parts[$i]
            }
            $folderPath = $folderPath + "\$name"
            ConvertTo-ShortNames $folderPath
        }
        $name++
    }
}

Ich weiß, dass dies eine alte Frage ist, aber ich dachte, ich würde sie hier stellen, falls jemand sie benötigt.

5
Mike Wallace

Es gibt eine Problemumgehung, die Experimental.IO aus Basisklassenbibliotheken Projekt verwendet. Sie finden es auf poshcode oder als Download von Autorenblog . Die Einschränkung wird von .NET abgeleitet, daher ist dies entweder die Folge oder die Verwendung von Tools, die nicht von .NET abhängen (wie cmd /c dir, wie @Bill vorgeschlagen hat).

3
BartekB

Dies wird alt, aber ich musste es kürzlich wieder umgehen. Am Ende habe ich "subst" verwendet, da keine anderen Module oder Funktionen auf dem PC verfügbar sein mussten, auf dem dies ausgeführt wurde. Ein bisschen portabler.

Suchen Sie im Grunde genommen einen freien Laufwerksbuchstaben, 'subst' den langen Pfad zu diesem Buchstaben, und verwenden Sie diesen als Basis für GCI.

Die einzige Einschränkung besteht darin, dass der vollständige Name $ _. Und andere Eigenschaften den Laufwerksbuchstaben als Stammpfad angeben.

Scheint ok zu funktionieren:

$location = \\path\to\long\
$driveLetter = ls function:[d-z]: -n | ?{ !(test-path $_) } | random

subst $driveLetter $location
sleep 1
Push-Location $driveLetter -ErrorAction SilentlyContinue
Get-ChildItem -Recurse

subst $driveLetter /D

Dieser Befehl dient offensichtlich nicht zum Löschen von Dateien, sondern kann ersetzt werden.

1
mhouston100

PowerShell kann problemlos mit AlphaFS.dll verwendet werden, um aktuelle Datei-E/A-Aufgaben zu erledigen, ohne dass der PATH TOO LONG-Aufwand auftritt.

Beispielsweise:

Import-Module <path-to-AlphaFS.dll>

[Alphaleonis.Win32.Filesystem.Directory]::Delete($path, $True)

Weitere Informationen zu diesem .NET-Projekt finden Sie unter Codeplex: https://alphafs.codeplex.com/ .

1
Shogun

Eine Kombination von Werkzeugen kann am besten funktionieren. Versuchen Sie, ein Verzeichnis/x zu erstellen, um stattdessen den 8.3-Dateinamen zu erhalten. Sie können diese Ausgabe dann in eine Textdatei auswerten und dann ein Powershell-Skript erstellen, um die Pfade zu löschen, die Sie aus der Datei entfernt haben. Nehmen Sie sich eine Minute Zeit. Alternativ können Sie den 8.3-Dateinamen auch in einen kürzeren Dateinamen umbenennen und dann löschen.

1
Zenbu

Für meine Robocopy hat in 1, 2 und 3 gearbeitet

  1. Erstellen Sie zuerst ein leeres Verzeichnis, sagen wir c:\emptydir
  2. ROBOCOPY c:\emptydir c:\directorytodelete/purge
  3. rmdir c:\directorytodelete
1
orellabac

Der Vollständigkeit halber bin ich noch ein paar Mal darauf gestoßen und habe eine Kombination aus "subst" und "New-PSDrive" verwendet, um das Problem in verschiedenen Situationen zu umgehen.

Nicht gerade eine Lösung, aber wenn jemand nach Alternativen sucht, könnte dies helfen.

Subst scheint sehr empfindlich auf die Art des Programms zu reagieren, mit dem Sie auf die Dateien zugreifen. Manchmal funktioniert es und manchmal nicht. Bei New-PSDrive scheint es dasselbe zu sein.

0
mhouston100

Ich hatte das gleiche Problem beim Versuch, Ordner auf einem Remotecomputer zu löschen.

Nichts hat geholfen, aber ... Ich habe einen Trick gefunden:

# 1:let's create an empty folder
md ".\Empty" -erroraction silentlycontinue

# 2: let's MIR to the folder to delete : this will empty the folder completely.
robocopy ".\Empty" $foldertodelete /MIR /LOG+:$logname 

# 3: let's delete the empty folder now:
remove-item $foldertodelete -force

# 4: we can delete now the empty folder
remove-item ".\Empty" -force

Funktioniert wie ein Zauber für lokale oder Remote-Ordner (unter Verwendung des UNC-Pfads)

0
Jean-Luc

Alles, was mit .NET entwickelt wurde, schlägt mit zu langen Pfaden fehl. Sie müssen sie in 8.3 Namen , PInVoke (Win32) -Aufrufe verschieben oder robocopy verwenden

0
DzSoundNirvana

Wenn das $ myDir in der Mitte Leerzeichen enthält, werden FILE NOT FOUND-Fehler angezeigt, wenn mehrere Dateien vom Speicherplatz getrennt werden. Um dies zu überwinden, verwenden Sie Anführungszeichen um die Variable und setzen Sie Powershell-Escape-Zeichen, um die Anführungszeichen zu überspringen.

PS>cmd.exe /C "rmdir /s /q <Grave-accent>"$myDir<Grave-accent>""

Bitte ersetzen Sie <Grave-accent> Durch das richtige Zeichen mit Grabakzent.
SO spielt mit mir und ich kann es nicht hinzufügen :). Hoffe, jemand wird es aktualisieren, damit andere es leicht verstehen

0