Impossible de supprimer un répertoire avec des crochets dans le nom à l'aide de WinSCP et PowerShell

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

  •  21-12-2019
  •  | 
  •  

Question

J'essaie d'écrire un script PowerShell qui supprime automatiquement les répertoires vides sur notre serveur FTP.Je n'ai pas d'accès direct au serveur sur lequel résident les répertoires - je ne peux y accéder que via FTP.Pour cette raison, j'ai écrit un script PowerShell qui utilise l'assembly WinSCP .NET pour (essayer de) supprimer les répertoires vides.Cependant, j'ai un problème dans la mesure où de nombreux répertoires sur le serveur ont des crochets dans le nom du répertoire.

Par exemple, le nom du répertoire peut s'appeler : [a]153432

Il existe beaucoup de ces répertoires, d'où mon envie d'écrire un script pour les supprimer.Cela se produit parce qu'ils ont été créés par un programme qui utilise un numéro pour créer les répertoires dont il a besoin.Afin de travailler sur ce programme, j'ai créé un répertoire vide

/latest/[b]test

Mon programme ressemble à ceci :

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

Lorsque je le lance, il affiche le message suivant :

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

Toutefois, le répertoire n'est pas supprimé.

J'ai également essayé de spécifier le nom du répertoire avec des délimiteurs tels que :

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

Mais cela échoue également (mais au moins c'est ce qui est dit) :

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

MAIS, si je change le nom du répertoire [et la variable $remoteFileWithUnixPath] à quelque chose comme

/latest/foo

Et puis relancez le programme, il supprime le répertoire /latest/foo ça va.

Quelqu'un a-t-il une idée de ce que je dois faire pour que cela fonctionne ?


La réponse à cette question a été soulignée par Martin Prikryl [Merci !]

Le code entièrement fonctionnel suit :

# 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
}
Était-ce utile?

La solution

Certaines méthodes de l'assembly WinSCP .NET, notamment la Session.RemoveFiles, acceptez un masque de fichier, pas un simple chemin.

Les crochets ont une signification particulière dans le masque de fichier.

Vous devriez toujours utiliser le RemotePath.EscapeFileMask méthode sur les chemins de fichiers, avant de les transmettre aux méthodes d'assemblage.

Autres conseils

J'utiliserais la séquence d'échappement dans la ligne de commande :

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

Ou utilisez le -LiteralPath paramètre.

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

Le paramètre -LiteralPath n'essaie pas de convertir la chaîne.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top