Impossibile eliminare una directory con parentesi quadre nel nome utilizzando WinSCP e PowerShell

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

  •  21-12-2019
  •  | 
  •  

Domanda

Sto provando a scrivere uno script PowerShell che elimini automaticamente le directory vuote sul nostro server FTP.Non ho accesso diretto al server su cui risiedono le directory, posso accedervi solo tramite FTP.Per questo motivo, ho scritto uno script PowerShell che utilizza l'assembly WinSCP .NET per (provare a) eliminare le directory vuote.Tuttavia, ho un problema, in quanto molte delle directory sul server hanno parentesi quadre nel nome della directory.

Ad esempio, il nome della directory potrebbe essere chiamato: [a]153432

Esistono molte di queste directory, da qui il mio desiderio di scrivere uno script per eliminarle.Ciò si verifica perché sono stati creati da un programma che utilizza un numero per creare le directory richieste.Per lavorare su questo programma, ho creato una directory vuota

/latest/[b]test

Il mio programma funziona così:

# 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
}

Quando lo eseguo, viene visualizzato il seguente messaggio:

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

Tuttavia, la directory non viene eliminata.

Ho anche provato a specificare il nome della directory con delimitatori come:

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

Ma anche questo fallisce (ma almeno lo dice):

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

MA, se cambio il nome della directory [e la variabile $remoteFileWithUnixPath] a qualcosa del genere

/latest/foo

E quindi rieseguire il programma, elimina la directory /latest/foo va bene.

Qualcuno ha qualche idea di cosa devo fare per farlo funzionare?


La risposta a questa domanda è stata sottolineata da Martin Prikryl [Grazie!]

Di seguito il codice completamente funzionante:

# 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
}
È stato utile?

Soluzione

Alcuni metodi dell'assembly WinSCP .NET, incluso the Session.RemoveFiles, accetta una maschera di file, non un percorso semplice.

Le parentesi quadre hanno un significato speciale nel maschera di file.

Dovresti sempre usare il file RemotePath.EscapeFileMask metodo sui percorsi dei file, prima di passarli ai metodi di assembly.

Altri suggerimenti

Utilizzerei la sequenza di escape nella riga di comando:

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

Oppure usa il -LiteralPath parametro.

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

Il parametro -LiteralPath non tenta di convertire la stringa.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top