使用 WinSCP .NET 程序集下载后移动(不复制)远程文件
Moving (not copying) remote files after download with WinSCP .NET assembly
我有这个脚本可以下载所有 .txt 和 .log 文件。但是我需要在下载后将它们移动到服务器上的另一个目录。
到目前为止,我一直收到类似 "cannot move "file" to "/file" 这样的错误。
try
{
# Load WinSCP .NET assembly
Add-Type -Path "C:\Program Files (x86)\WinSCP\WinSCPnet.dll"
# Setup session options
$sessionOptions = New-Object WinSCP.SessionOptions
$sessionOptions.Protocol = [WinSCP.Protocol]::ftp
$sessionOptions.HostName = "host"
$sessionOptions.PortNumber = "port"
$sessionOptions.UserName = "user"
$sessionOptions.Password = "pass"
$session = New-Object WinSCP.Session
try
{
# Connect
$session.DisableVersionCheck = "true"
$session.Open($sessionOptions)
$localPath = "C:\users\user\desktop\file"
$remotePath = "/"
$fileName = "*.txt"
$fileNamee = "*.log"
$remotePath2 = "/completed"
$directoryInfo = $session.ListDirectory($remotePath)
$directoryInfo = $session.ListDirectory($remotePath2)
# Download the file
$session.GetFiles(($remotePath + $fileName), $localPath).Check()
$session.GetFiles(($remotePath + $fileNamee), $localPath).Check()
$session.MoveFile(($remotePath + $fileName, $remotePath2)).Check()
$session.MoveFile(($remotePath + $fileNamee, $remotePath2)).Check()
}
finally
{
# Disconnect, clean up
$session.Dispose()
}
exit 0
}
catch [Exception]
{
Write-Host $_.Exception.Message
exit 1
}
您是否检查过以确保您的进程有权将文件移动到新目录?
你的代码有很多问题:
Session.MoveFile
方法的 targetPath
参数是 move/rename 文件的路径。
因此,如果您使用目标路径 /complete
,您正试图将文件移动到根文件夹并将其重命名为 complete
。虽然您可能想将文件移动到 /complete
文件夹并保留其名称。为此,使用目标路径 /complete/
(或 /complete/*
使其更明显)。
您当前的代码失败,因为您正在将文件重命名为现有文件夹的名称。
您实际上在 .GetFiles
中有相同的错误。您正在将所有文件(*.txt
和 *.log
)下载到文件夹 C:\users\user\desktop
并将它们全部保存到相同的名称 file
,相互覆盖。
你用括号错误地包围了两个参数,而不是只包围了第一个参数。虽然我不是 PowerShell 专家,但我实际上会说您以这种方式完全省略了该方法的第二个参数。
此外,请注意 MoveFile
方法不会 return 任何东西(与 GetFiles
相反)。所以没有对象可以调用 .Check()
方法。
MoveFile
(注意单数,与GetFiles
相比),只移动一个文件。所以你不应该使用文件掩码。实际上,当前的实现允许使用文件掩码,但这种使用没有记录在案,可能会在未来的版本中弃用。
无论如何,最好的解决方案是迭代实际下载文件的列表,如 GetFiles
编辑的 return 并一个一个地移动文件。
这样可以避免竞争条件,下载文件集,添加新文件(您没有下载)并且错误地将它们移动到 "completed" 文件夹。
代码应该如下所示(仅针对第一组文件,即 *.txt
):
$remotePath2 = "/completed/"
...
$transferResult = $session.GetFiles(($remotePath + $fileName), $localPath)
$transferResult.Check()
foreach ($transfer in $transferResult.Transfers)
{
$session.MoveFile($transfer.FileName, $remotePath2)
}
请注意,这不包括对 $localPath
的修复,因为我不确定路径 C:\users\user\desktop\file
的实际含义。
实际上有一个非常相似的示例代码可用:
Moving local files to different location after successful upload
我正在按照 Martin 在这里的建议行事,并取得了成功。
但我有时会卡住。
运行“session.MoveFile()”后,源文件夹中的文件消失了,但目标文件夹中没有显示。
文件将在一段时间后(我猜是大约 30 分钟)自动处理“会话”后显示到目的地。
为避免这种混淆,请释放会话。
像这样:
session.Dispose();
我知道这是微不足道的,但我希望你不要陷入同样的问题。
我有这个脚本可以下载所有 .txt 和 .log 文件。但是我需要在下载后将它们移动到服务器上的另一个目录。
到目前为止,我一直收到类似 "cannot move "file" to "/file" 这样的错误。
try
{
# Load WinSCP .NET assembly
Add-Type -Path "C:\Program Files (x86)\WinSCP\WinSCPnet.dll"
# Setup session options
$sessionOptions = New-Object WinSCP.SessionOptions
$sessionOptions.Protocol = [WinSCP.Protocol]::ftp
$sessionOptions.HostName = "host"
$sessionOptions.PortNumber = "port"
$sessionOptions.UserName = "user"
$sessionOptions.Password = "pass"
$session = New-Object WinSCP.Session
try
{
# Connect
$session.DisableVersionCheck = "true"
$session.Open($sessionOptions)
$localPath = "C:\users\user\desktop\file"
$remotePath = "/"
$fileName = "*.txt"
$fileNamee = "*.log"
$remotePath2 = "/completed"
$directoryInfo = $session.ListDirectory($remotePath)
$directoryInfo = $session.ListDirectory($remotePath2)
# Download the file
$session.GetFiles(($remotePath + $fileName), $localPath).Check()
$session.GetFiles(($remotePath + $fileNamee), $localPath).Check()
$session.MoveFile(($remotePath + $fileName, $remotePath2)).Check()
$session.MoveFile(($remotePath + $fileNamee, $remotePath2)).Check()
}
finally
{
# Disconnect, clean up
$session.Dispose()
}
exit 0
}
catch [Exception]
{
Write-Host $_.Exception.Message
exit 1
}
您是否检查过以确保您的进程有权将文件移动到新目录?
你的代码有很多问题:
Session.MoveFile
方法的 targetPath
参数是 move/rename 文件的路径。
因此,如果您使用目标路径 /complete
,您正试图将文件移动到根文件夹并将其重命名为 complete
。虽然您可能想将文件移动到 /complete
文件夹并保留其名称。为此,使用目标路径 /complete/
(或 /complete/*
使其更明显)。
您当前的代码失败,因为您正在将文件重命名为现有文件夹的名称。
您实际上在 .GetFiles
中有相同的错误。您正在将所有文件(*.txt
和 *.log
)下载到文件夹 C:\users\user\desktop
并将它们全部保存到相同的名称 file
,相互覆盖。
你用括号错误地包围了两个参数,而不是只包围了第一个参数。虽然我不是 PowerShell 专家,但我实际上会说您以这种方式完全省略了该方法的第二个参数。
此外,请注意 MoveFile
方法不会 return 任何东西(与 GetFiles
相反)。所以没有对象可以调用 .Check()
方法。
MoveFile
(注意单数,与GetFiles
相比),只移动一个文件。所以你不应该使用文件掩码。实际上,当前的实现允许使用文件掩码,但这种使用没有记录在案,可能会在未来的版本中弃用。
无论如何,最好的解决方案是迭代实际下载文件的列表,如 GetFiles
编辑的 return 并一个一个地移动文件。
这样可以避免竞争条件,下载文件集,添加新文件(您没有下载)并且错误地将它们移动到 "completed" 文件夹。
代码应该如下所示(仅针对第一组文件,即 *.txt
):
$remotePath2 = "/completed/"
...
$transferResult = $session.GetFiles(($remotePath + $fileName), $localPath)
$transferResult.Check()
foreach ($transfer in $transferResult.Transfers)
{
$session.MoveFile($transfer.FileName, $remotePath2)
}
请注意,这不包括对 $localPath
的修复,因为我不确定路径 C:\users\user\desktop\file
的实际含义。
实际上有一个非常相似的示例代码可用:
Moving local files to different location after successful upload
我正在按照 Martin 在这里的建议行事,并取得了成功。
但我有时会卡住。
运行“session.MoveFile()”后,源文件夹中的文件消失了,但目标文件夹中没有显示。
文件将在一段时间后(我猜是大约 30 分钟)自动处理“会话”后显示到目的地。
为避免这种混淆,请释放会话。 像这样:
session.Dispose();
我知道这是微不足道的,但我希望你不要陷入同样的问题。