Ein Verzeichnis mit eckigen Klammern im Namen kann mit WinSCP und PowerShell nicht gelöscht werden

StackOverflow https://stackoverflow.com//questions/22032008

  •  21-12-2019
  •  | 
  •  

Frage

Ich versuche, ein PowerShell-Skript zu schreiben, das leere Verzeichnisse auf unserem FTP-Server automatisch löscht.Ich habe keinen direkten Zugriff auf den Server, auf dem die Verzeichnisse liegen, sondern kann nur per FTP darauf zugreifen.Aus diesem Grund habe ich ein PowerShell-Skript geschrieben, das die WinSCP .NET-Assembly verwendet, um die leeren Verzeichnisse zu löschen (zu versuchen).Allerdings habe ich ein Problem, da viele Verzeichnisse auf dem Server eckige Klammern im Verzeichnisnamen haben.

Der Verzeichnisname könnte beispielsweise wie folgt lauten: [a]153432

Es gibt viele dieser Verzeichnisse, daher möchte ich ein Skript schreiben, um sie zu löschen.Dies liegt daran, dass sie von einem Programm erstellt wurden, das eine Nummer verwendet, um die erforderlichen Verzeichnisse zu erstellen.Um an diesem Programm arbeiten zu können, habe ich ein leeres Verzeichnis erstellt

/latest/[b]test

Mein Programm sieht so aus:

# program to test deletion of directories with square-brackets in the name.

$HOSTNAME="myftpservername"
$USERNAME="myftpusername"
$PASSWORD="myftppassword"
$DLL_LOCATION="C:\Program Files (x86)\WinSCP\WinSCPnet.dll"
$LOCAL_DIRECTORY="C:\testdir\extended\baseroot"

# Load WinSCP .NET assembly
[Reflection.Assembly]::LoadFrom($DLL_LOCATION) | Out-Null

# Session.FileTransferred event handler

try
{
    $sessionOptions = New-Object WinSCP.SessionOptions
    $sessionOptions.Protocol = [WinSCP.Protocol]::ftp
    $sessionOptions.HostName = $HOSTNAME
    $sessionOptions.UserName = $USERNAME
    $sessionOptions.Password = $PASSWORD

    $session = New-Object WinSCP.Session
    try
    {
        # Connect
        $session.Open($sessionOptions)

        $remoteFileWithUnixPath = "/latest/[b]test"

        $removalResult = $session.RemoveFiles($remoteFileWithUnixPath)
        if ($removalResult.IsSuccess)
        {
            Write-Host ("Removal of remote file {0} succeeded" -f $remoteFileWithUnixPath)
        }
        else
        {
            Write-Host ("Removal of remote file {0} failed" -f $remoteFileWithUnixPath)
        }
    }
    finally
    {
        # Disconnect, clean up
        $session.Dispose()
    }
    exit 0
}
catch [Exception]
{
    Write-Host $_.Exception.Message
    exit 1
}

Wenn ich es ausführe, wird die folgende Meldung angezeigt:

PS C:\Users\dbuddrige\Documents\dps> .\delete-squarebracket-dir.ps1
Removal of remote file /latest/[b]test succeeded

Das Verzeichnis wird jedoch nicht gelöscht.

Ich habe auch versucht, den Verzeichnisnamen mit Trennzeichen anzugeben, wie zum Beispiel:

$remoteFileWithUnixPath = "/latest/\[b\]test"

Aber auch das schlägt fehl (sagt es aber zumindest):

PS C:\Users\dbuddrige\Documents\dps> .\delete-squarebracket-dir.ps1
Removal of remote file /latest/\[b\]test failed

ABER wenn ich den Verzeichnisnamen [und die Variable $remoteFileWithUnixPath] zu so etwas wie

/latest/foo

Wenn Sie das Programm dann erneut ausführen, wird das Verzeichnis gelöscht /latest/foo Alles gut.

Hat jemand eine Idee, was ich tun muss, damit das funktioniert?


Die Antwort auf diese Frage wurde von Martin Prikryl gegeben [Danke!]

Der voll funktionsfähige Code folgt:

# program to test deletion of directories with square-brackets in the name.

$HOSTNAME="myftpservername"
$USERNAME="myftpusername"
$PASSWORD="myftppassword"
$DLL_LOCATION="C:\Program Files (x86)\WinSCP\WinSCPnet.dll"
$LOCAL_DIRECTORY="C:\testdir\extended\baseroot"

# Load WinSCP .NET assembly
[Reflection.Assembly]::LoadFrom($DLL_LOCATION) | Out-Null

# Session.FileTransferred event handler

try
{
    $sessionOptions = New-Object WinSCP.SessionOptions
    $sessionOptions.Protocol = [WinSCP.Protocol]::ftp
    $sessionOptions.HostName = $HOSTNAME
    $sessionOptions.UserName = $USERNAME
    $sessionOptions.Password = $PASSWORD

    $session = New-Object WinSCP.Session
    try
    {
        # Connect
        $session.Open($sessionOptions)

        $remoteFileWithUnixPath = "/latest/[b]test"

        $removalResult = 
            $session.RemoveFiles($session.EscapeFileMask($remoteFileWithUnixPath))
        if ($removalResult.IsSuccess)
        {
            Write-Host ("Removal of remote file {0} succeeded" -f $remoteFileWithUnixPath)
        }
        else
        {
            Write-Host ("Removal of remote file {0} failed" -f $remoteFileWithUnixPath)
        }
    }
    finally
    {
        # Disconnect, clean up
        $session.Dispose()
    }
    exit 0
}
catch [Exception]
{
    Write-Host $_.Exception.Message
    exit 1
}
War es hilfreich?

Lösung

Einige Methoden der WinSCP .NET-Assembly, einschließlich der Session.RemoveFiles, akzeptieren Sie eine Dateimaske, keinen einfachen Pfad.

Eckige Klammern haben dabei eine besondere Bedeutung Dateimaske.

Sie sollten immer die verwenden RemotePath.EscapeFileMask Methode auf Dateipfaden, bevor sie an Assemblermethoden übergeben werden.

Andere Tipps

Ich würde die Escape-Sequenz in der Befehlszeile verwenden:

Remove-Item 'C:\Scripts\Test`[1`].txt'

Oder nutzen Sie die -LiteralPath Parameter.

Remove-Item -LiteralPath C:\scripts\test[1].txt

Der Parameter -LiteralPath versucht nicht, die Zeichenfolge zu konvertieren.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top