Impossibile eliminare una directory con parentesi quadre nel nome utilizzando WinSCP e PowerShell
-
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
}
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.