No se puede eliminar un directorio con corchetes en el nombre con el WinSCP y PowerShell

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

  •  21-12-2019
  •  | 
  •  

Pregunta

Estoy tratando de escribir un script de PowerShell que elimina automáticamente los directorios vacíos en nuestro servidor FTP.No tengo ningún acceso directo al servidor en el que los directorios residen - sólo puedo acceder a ellos a través de FTP.Por esta razón, he escrito un script de PowerShell que utiliza el WinSCP .NETO de la asamblea para (intentar) eliminar los directorios vacíos.Sin embargo, tengo un problema, en que muchos de los directorios en el servidor tiene corchetes en el nombre del directorio.

Por ejemplo, el nombre del directorio puede ser denominado: [a]153432

Hay un montón de estos directorios, de ahí mi deseo de escribir una secuencia de comandos para eliminar de ellos.Esto ocurre porque han sido creados por un programa que utiliza un número para crear los directorios que se requiere.Con el fin de trabajar en este programa, he creado un directorio vacío

/latest/[b]test

Mi programa va como esto:

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

Cuando se ejecuta, muestra el siguiente mensaje:

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

Sin embargo, el directorio no se elimina.

También he tratado de especificar el nombre del directorio con delimitadores, tales como:

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

Pero esto también falla (al menos eso dice):

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

PERO, si puedo cambiar el nombre del directorio [y la variable $remoteFileWithUnixPath] a algo como

/latest/foo

Y, a continuación, vuelva a ejecutar el programa, borra el directorio /latest/foo bien.

¿Alguien tiene alguna idea de lo que tengo que hacer para conseguir que esto funcione?


La respuesta a esta pregunta fue señalado por Martín Prikryl [Gracias!]

Completamente el código de trabajo de la siguiente manera:

# 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
}
¿Fue útil?

Solución

Algunos métodos de la WinSCP .NETO de la asamblea, incluyendo la Session.RemoveFiles, aceptar una máscara de archivo, no es un camino simple.

Los corchetes tienen un significado especial en la la máscara de archivo.

Usted siempre debe usar el RemotePath.EscapeFileMask método en rutas de acceso de archivo, antes de pasar a los métodos de montaje.

Otros consejos

Me gustaría usar la secuencia de escape en la línea de comandos:

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

O utilizar el -LiteralPath parámetro.

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

La LiteralPath parámetro no intenta convertir la cadena.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top