使用WinSCP .NET程序集下载后移动(不复制)远程文件

时间:2015-02-10 16:36:56

标签: powershell ftp winscp winscp-net

我有这个脚本可以下载所有.txt和.log文件。但是我需要在下载后将它们移动到服务器上的另一个目录中。

到目前为止,我只是不断收到错误,例如"无法移动"文件"到" /文件"

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
}

3 个答案:

答案 0 :(得分:1)

您的代码中存在许多问题:


Session.MoveFile方法的targetPath参数是将文件移动/重命名为的路径。

因此,如果您使用目标路径/complete,则尝试将文件移动到根文件夹并将其重命名为complete。虽然您可能希望将文件移动到/complete文件夹,并保留其名称。为此,使用目标路径/complete/(或/complete/*使其更明显)。

您当前的代码失败,因为您正在将文件重命名为现有文件夹的名称。


您实际上在.GetFiles中遇到了同样的错误。您正在将所有文件({1}}和*.txt)下载到文件夹*.log,并将它们全部保存为同名C:\users\user\desktop,并相互覆盖。


两个参数周围都有错误的括号,而不是仅围绕第一个参数。虽然我不是PowerShell专家,但我实际上说你完全以这种方式省略了该方法的第二个参数。


此外,请注意file方法不会返回任何内容(与GetFiles相反)。因此,无法调用MoveFile方法。


.Check()(注意单数,与MoveFile比较),只移动一个文件。所以你不应该使用文件掩码。实际上,本实现允许使用文件掩码,但是这种用法没有记录,在将来的版本中可能会被弃用。

无论如何,最好的解决方案是迭代实际下载的文件列表,由GetFiles返回并逐个移动文件。

这样你可以避免竞争条件,你下载文件集,添加新文件(你没有下载),你错误地将它们移动到"已完成"文件夹中。


代码应如下(仅适用于第一组文件,即GetFiles):

*.txt

请注意,这不包括$remotePath2 = "/completed/" ... $transferResult = $session.GetFiles(($remotePath + $fileName), $localPath) $transferResult.Check() foreach ($transfer in $transferResult.Transfers) { $session.MoveFile(($remotePath + $transfer.FileName), $remotePath2) } 的修正,因为我不确定路径$localPath的实际含义。


实际上有一个非常相似的示例代码:
Moving local files to different location after successful upload

答案 1 :(得分:0)

您是否检查过以确保您的进程有权将文件移动到新目录?

答案 2 :(得分:0)

我正在按照马丁在这里的建议成功地做。

但我有时被卡住了。

运行“session.MoveFile()”后,原始文件夹中的文件消失了,但目标文件夹中没有显示。

在一段时间(我猜大约 30 分钟)后自动处理“会话”后,文件将显示到目的地。

为避免这种混淆,请处理会话。 像这样:

session.Dispose();

我知道这是微不足道的,但我希望你不会遇到同样的问题。