Невозможно удалить каталог с квадратными скобками в имени с помощью WinSCP и PowerShell.

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

  •  21-12-2019
  •  | 
  •  

Вопрос

Я пытаюсь написать сценарий PowerShell, который автоматически удаляет пустые каталоги на нашем FTP-сервере.У меня нет прямого доступа к серверу, на котором находятся каталоги, я могу получить к ним доступ только через FTP.По этой причине я написал сценарий PowerShell, который использует сборку WinSCP .NET для (попытки) удаления пустых каталогов.Однако у меня есть проблема: многие каталоги на сервере имеют в имени каталога квадратные скобки.

Например, имя каталога может называться: [a]153432

Таких каталогов очень много, отсюда и мое желание написать скрипт для их удаления.Это происходит потому, что они были созданы программой, которая использует номер для создания необходимых ей каталогов.Для работы с этой программой я создал пустой каталог

/latest/[b]test

Моя программа выглядит следующим образом:

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

Когда я запускаю его, он отображает следующее сообщение:

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

Однако каталог не удаляется.

Я также попытался указать имя каталога с разделителями, например:

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

Но это тоже не получается (но, по крайней мере, так сказано):

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

НО, если я изменю имя каталога [и переменную $remoteFileWithUnixPath] к чему-то вроде

/latest/foo

А потом перезапустить программу, она удалит каталог /latest/foo просто хорошо.

Есть ли у кого-нибудь идеи, что мне нужно сделать, чтобы это заработало?


Ответ на этот вопрос указал Мартин Прикрыл [Спасибо!]

Полностью рабочий код следующий:

# 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
}
Это было полезно?

Решение

Некоторые методы сборки WinSCP .NET, в том числе метод Session.RemoveFiles, примите маску файла, а не простой путь.

Квадратные скобки имеют особое значение в маска файла.

Вы всегда должны использовать RemotePath.EscapeFileMask метод по путям к файлам, прежде чем передавать их методам сборки.

Другие советы

Я бы использовал escape-последовательность в командной строке:

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

Или используйте -LiteralPath параметр.

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

Параметр -LiteralPath не пытается преобразовать строку.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top