[英]PowerShell How can I delete a directory with FTP?
从这个Web 请求方法字段列表中,我已经通过 FTP 成功地从我的服务器中删除了文件,基本上是在此页面上填写指南并稍作改动:
$url = "ftp://server.net/path/to/place/FILE.txt"
$userName = "username"
$password = "p@ssw0rd!"
$ftpreq = [System.Net.FtpWebRequest]::create($url)
$ftpreq.Credentials = New-Object System.Net.NetworkCredential($userName, $password)
$ftpreq.Method = [System.Net.WebRequestMethods+Ftp]::DeleteFile
$ftpreq.GetResponse()
该文件名为FILE.txt
,文件夹名为FOLDER
。
当我尝试对文件夹执行类似操作时,我收到 PowerShell 错误和 550 响应。
我基本上尝试了文件删除方法的两种变体。
请注意,我尝试删除的文件夹位于我已成功删除的文件旁边。
$url = "ftp://server.net/path/to/place/FOLDER"
$userName = "username"
$password = "p@ssw0rd!"
$ftpreq = [System.Net.FtpWebRequest]::create($url)
$ftpreq.Credentials = New-Object System.Net.NetworkCredential($userName, $password)
$ftpreq.Method = [System.Net.WebRequestMethods+Ftp]::DeleteFile
$ftpreq.GetResponse()
使用“0”参数调用“GetResponse”的异常:“远程服务器返回错误:(550) 文件不可用(例如,找不到文件,无法访问)。
$url = "ftp://server.net/path/to/place/FOLDER"
$userName = "username"
$password = "p@ssw0rd!"
$ftpreq = [System.Net.FtpWebRequest]::create($url)
$ftpreq.Credentials = New-Object System.Net.NetworkCredential($userName, $password)
$ftpreq.Method = [System.Net.WebRequestMethods+Ftp]::RemoveDirectory
$ftpreq.GetResponse()
使用“0”参数调用“GetResponse”的异常:“远程服务器返回错误:(550) 文件不可用(例如,找不到文件,无法访问)。”
function DeleteFtpFolder($url, $credentials)
{
$listRequest = [Net.WebRequest]::Create($url)
$listRequest.Method = [System.Net.WebRequestMethods+FTP]::ListDirectoryDetails
$listRequest.Credentials = $credentials
$lines = New-Object System.Collections.ArrayList
$listResponse = $listRequest.GetResponse()
$listStream = $listResponse.GetResponseStream()
$listReader = New-Object System.IO.StreamReader($listStream)
while (!$listReader.EndOfStream)
{
$line = $listReader.ReadLine()
$lines.Add($line) | Out-Null
}
$listReader.Dispose()
$listStream.Dispose()
$listResponse.Dispose()
foreach ($line in $lines)
{
$tokens = $line.Split(" ", 5, [System.StringSplitOptions]::RemoveEmptyEntries)
$type = $tokens[2]
$name = $tokens[3]
$fileUrl = ($url + "/" + $name)
if ($type -eq "<DIR>")
{
Write-Host "Found folder: $name"
DeleteFtpFolder $fileUrl $credentials
Write-Host "Deleting folder: $name"
$deleteRequest = [Net.WebRequest]::Create($fileUrl)
$deleteRequest.Credentials = $credentials
$deleteRequest.Method = [System.Net.WebRequestMethods+FTP]::RemoveDirectory
$deleteRequest.GetResponse() | Out-Null
}
else
{
$fileUrl = ($url + "/" + $name)
Write-Host "Deleting file: $name"
$deleteRequest = [Net.WebRequest]::Create($fileUrl)
$deleteRequest.Credentials = $credentials
$deleteRequest.Method = [System.Net.WebRequestMethods+FTP]::DeleteFile
$deleteRequest.GetResponse() | Out-Null
}
}
}
$credentials = New-Object System.Net.NetworkCredential($AzureFtpUsername, $AzureFtpPassword)
$url = $AzureFtpUrl
DeleteFtpFolder $url $credentials
该设置是 Octopus Deploy 内流程步骤中的嵌入式 PowerShell 脚本。 这就是我在底部调用函数的原因。
该解决方案与接受的答案几乎相同,只是对我放置递归调用的位置以及如何解析从服务器返回的数据进行了一些小的改动。 他的解决方案看起来更像是ls
输出,列更多,而我的解决方案看起来更像是dir
输出,列更少。 但即便如此,它看起来不像我本地 Windows 机器上的dir
输出,所以我不确定到底发生了什么。 但它有效,所以这就足够了。
如果目录不为空,则RMD
FTP命令( RemoveDirectory
方法)失败。
通常,它会失败并显示以下错误:
550目录不为空。
不幸的是, FtpWebRequest
具有将FTP错误代码“转换”为自己的消息的坏习惯。 在这种情况下,它将“翻译” 550为:
文件不可用(例如,找不到文件,无法访问)。
什么隐藏了真正的问题。
无论如何, FtpWebRequest
类 (或.NET框架中的任何其他FTP实现)都不支持递归操作。 您必须自己实现递归:
棘手的部分是从子目录中识别文件。 使用FtpWebRequest
无法以可移植的方式完成此操作。 不幸的是, FtpWebRequest
不支持MLSD
命令,这是在FTP协议中检索带有文件属性的目录列表的唯一便携式方法。 另请参阅检查FTP服务器上的对象是文件还是目录 。
您的选择是:
LIST
命令= ListDirectoryDetails
方法)并尝试解析服务器特定的列表。 许多FTP服务器使用* nix样式的列表,您可以在条目的开头用d
标识目录。 但是许多服务器使用不同的格式。 下面的示例使用这种方法(假设* nix格式)。 function DeleteFtpFolder($url, $credentials)
{
$listRequest = [Net.WebRequest]::Create($url)
$listRequest.Method = [System.Net.WebRequestMethods+Ftp]::ListDirectoryDetails
$listRequest.Credentials = $credentials
$lines = New-Object System.Collections.ArrayList
$listResponse = $listRequest.GetResponse()
$listStream = $listResponse.GetResponseStream()
$listReader = New-Object System.IO.StreamReader($listStream)
while (!$listReader.EndOfStream)
{
$line = $listReader.ReadLine()
$lines.Add($line) | Out-Null
}
$listReader.Dispose()
$listStream.Dispose()
$listResponse.Dispose()
foreach ($line in $lines)
{
$tokens = $line.Split(" ", 9, [StringSplitOptions]::RemoveEmptyEntries)
$name = $tokens[8]
$permissions = $tokens[0]
$fileUrl = ($url + $name)
if ($permissions[0] -eq 'd')
{
DeleteFtpFolder ($fileUrl + "/") $credentials
}
else
{
Write-Host "Deleting file $name"
$deleteRequest = [Net.WebRequest]::Create($fileUrl)
$deleteRequest.Credentials = $credentials
$deleteRequest.Method = [System.Net.WebRequestMethods+Ftp]::DeleteFile
$deleteRequest.GetResponse() | Out-Null
}
}
Write-Host "Deleting folder"
$deleteRequest = [Net.WebRequest]::Create($url)
$deleteRequest.Credentials = $credentials
$deleteRequest.Method = [System.Net.WebRequestMethods+Ftp]::RemoveDirectory
$deleteRequest.GetResponse() | Out-Null
}
使用如下功能:
$url = "ftp://ftp.example.com/path/to/folder/";
$credentials = New-Object System.Net.NetworkCredential("username", "password")
DeleteFtpFolder $url $credentials
或使用支持递归操作的第3方库。
例如,使用WinSCP .NET程序集,您可以通过一次调用Session.RemoveFiles
来删除整个目录:
# Load WinSCP .NET assembly
Add-Type -Path "WinSCPnet.dll"
# Setup session options
$sessionOptions = New-Object WinSCP.SessionOptions -Property @{
Protocol = [WinSCP.Protocol]::Ftp
HostName = "ftp.example.com"
UserName = "username"
Password = "password"
}
$session = New-Object WinSCP.Session
# Connect
$session.Open($sessionOptions)
# Remove folder
$session.RemoveFiles("/path/to/folder").Check()
# Disconnect, clean up
$session.Dispose()
如果服务器支持,WinSCP在内部使用MLSD
命令。 如果没有,它将使用LIST
命令并支持多种不同的列表格式。
(我是WinSCP的作者)
Martin Prikryl 对 Azure FTP 的回答几乎没有变化
这将适用于以下格式
"01-12-22 07:38AM <DIR> assets"
"12-16-21 12:22PM 959 African Union.png"
function DeleteFtpFolder( $url, $credentials)
{
$listRequest = [Net.WebRequest]::Create($url)
$listRequest.Method = [System.Net.WebRequestMethods+Ftp]::ListDirectoryDetails
$listRequest.Credentials = $credentials
$lines = New-Object System.Collections.ArrayList
$listResponse = $listRequest.GetResponse()
$listStream = $listResponse.GetResponseStream()
$listReader = New-Object System.IO.StreamReader($listStream)
while (!$listReader.EndOfStream)
{
$line = $listReader.ReadLine()
$lines.Add($line) | Out-Null
}
$listReader.Dispose()
$listStream.Dispose()
$listResponse.Dispose()
foreach ($line in $lines)
{
$tokens = $line.split(" ", 4, StringSplitOptions]::RemoveEmptyEntries)
$name = $tokens[3]
$permissions = $tokens[2]
$fileUrl = ($url + $name)
if ($permissions[0] -eq '<dir>')
{
DeleteFtpFolder ($fileUrl + "/") $credentials
}
else
{
Write-Host "Deleting file $name"
$deleteRequest = [Net.WebRequest]::Create($fileUrl)
$deleteRequest.Credentials = $credentials
$deleteRequest.Method = [System.Net.WebRequestMethods+Ftp]::DeleteFile
$deleteRequest.GetResponse() | Out-Null
}
}
Write-Host "Deleting folder"
$deleteRequest = [Net.WebRequest]::Create($url)
$deleteRequest.Credentials = $credentials
$deleteRequest.Method = [System.Net.WebRequestMethods+Ftp]::RemoveDirectory
$deleteRequest.GetResponse() | Out-Null
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.