无法使用 WinSCP 和 PowerShell 删除名称中带有方括号的目录
-
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
正好。
有谁知道我需要做什么才能让它发挥作用?
Martin Prikryl 指出了这个问题的答案 [谢谢!]
完整的工作代码如下:
# 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
方法 在将文件路径传递给汇编方法之前。
其他提示
我会在命令行中使用转义序列:
Remove-Item 'C:\Scripts\Test`[1`].txt'
或者使用 -LiteralPath
范围。
Remove-Item -LiteralPath C:\scripts\test[1].txt
-LiteralPath 参数不会尝试转换字符串。
不隶属于 StackOverflow