如何比较本地文件与 FTP 服务器上文件的使用年限,如果远程副本在 PowerShell 中较新则如何下载

How to compare age of local file with file on FTP server and download if remote copy is newer in PowerShell

我正在编写一个 PowerShell 脚本来帮助我为工作设置新 PC。这有望被不止我一个人使用,所以我正在努力考虑所有事情。

我有离线安装程序(java、flash、reader 等)保存在我们的 FTP 服务器上,如果尚未保存本地副本,脚本会下载该服务器创建的 Apps 目录。随着新版本程序的发布,FTP 服务器上的文件将定期更新。我希望脚本可以选择检查安装程序的较新版本,以防有人喜欢随身携带本地副本而忘记不时检查服务器。它还需要在 Windows 7 中工作,而不需要导入额外的模块,除非有一种简单的方法可以同时在多台 PC 上执行此操作。我知道 import 命令,但我的经验需要我将模块文件复制到 PC 上的多个位置才能工作。

现在我还没有找到任何解决方案。我找到了检查本地文件或本地服务器上的文件的修改日期的代码,但除了 uploading\downloading 个文件之外,没有任何其他处理 FTP 的代码。

这是我尝试的最后一件事。我尝试将我为本地文件找到的内容与 FTP 结合使用。效果不太好。

我是 PowerShell 的新手,但到目前为止,我非常擅长将这一切拼凑在一起。然而,这个想法越来越麻烦了。

感谢您的帮助。

$ftpsite = "ftp://ftpsite.com/folder/"

$firefox = (Get-Item $dir\Apps\install_firefox.exe).LastWriteTime.toString("MM/dd/yyyy")

if ($firefoxftp = (Get-ChildItem $ftpsite/install_firefox.exe | Where{$_.LastWriteTime -gt $firefox})) {

    $File = "$dir\Apps\install_firefox.exe"
    $ftp = "ftp://ftpsite.com/folder/install_firefox.exe"
    $webclient = New-Object System.Net.WebClient
    $uri = New-Object System.Uri($ftp)
    $webclient.DownloadFile($uri, $File)

}

更新:

这是在 Martin 的帮助下我得到的。有点管用。它从 FTP 下载文件,但没有正确比较远程和本地。远程文件 returns 20150709140505 和本地文件 returns 07/09/2015 2:05:05 PM。我如何在比较前格式化一个看起来像另一个,“-gt”是正确的比较使用吗?

谢谢!

function update {

    $ftprequest = [System.Net.FtpWebRequest]::Create("ftp://ftpsite.com/Script_Apps/install_firefox.exe")
    $ftprequest.Method = [System.Net.WebRequestMethods+Ftp]::GetDateTimestamp
    $response = $ftprequest.GetResponse().StatusDescription
    $tokens = $response.Split(" ")
    $code = $tokens[0]

    $localfile = (Get-Item "$dir\Apps\install_firefox.exe").LastWriteTimeUtc

    if ($tokens -gt $localfile) {

        write-host "Updating Firefox Installer..."
        $File = "$dir\Apps\install_firefox.exe"
        $ftp = "ftp://ftpsite.com/Script_Apps/install_firefox.exe"
        $webclient = New-Object System.Net.WebClient
        $uri = New-Object System.Uri($ftp)
        $webclient.DownloadFile($uri, $File)

        "Updated Firefox" >> $global:logfile

        mainmenu

    }

    else {
        Write-Host "Local Copy is Newer."
        sleep 3
        mainmenu
    }

}

更新 2:

似乎有效!这是代码。感谢您的帮助!

function update {

    $ftprequest = [System.Net.FtpWebRequest]::Create("ftp://ftpserver.com/Script_Apps/install_firefox.exe")
    $ftprequest.Method = [System.Net.WebRequestMethods+Ftp]::GetDateTimestamp
    $response = $ftprequest.GetResponse().StatusDescription
    $tokens = $response.Split(" ")
    $code = $tokens[0]

    $localtime = (Get-Item "$dir\Apps\install_firefox.exe").LastWriteTimeUtc

    if ($code -eq 213) {

        $tokens = $tokens[1]
        $localtime = "{0:yyyymmddHHmmss}" -f [datetime]$localtime

    }

    if ($tokens -gt $localtime) {

        write-host "Updating Firefox Installer..."
        $File = "$dir\Apps\install_firefox.exe"
        $ftp = "ftp://ftpserver.com/Script_Apps/install_firefox.exe"
        $webclient = New-Object System.Net.WebClient
        $uri = New-Object System.Uri($ftp)
        $webclient.DownloadFile($uri, $File)

        "Updated Firefox" >> $global:logfile

        mainmenu

    }

    else {
        Write-Host "Local Copy is Newer."
        sleep 3
        mainmenu
    }

}

您不能使用 WebClient class 检查远程文件时间戳。

你可以使用 FtpWebRequest class with its GetDateTimestamp FTP "method" and parse the UTC timestamp string it returns. The format is specified by RFC 3659YYYYMMDDHHMMSS[.sss]

仅当 FTP 服务器支持该方法在幕后使用的 MDTM 命令时才有效(大多数服务器支持,但不是全部)。

$url = "ftp://ftpsite.com/folder/install_firefox.exe"
$ftprequest = [System.Net.FtpWebRequest]::Create($url)

$ftprequest.Method = [System.Net.WebRequestMethods+Ftp]::GetDateTimestamp

$response = $ftprequest.GetResponse().StatusDescription

$tokens = $response.Split(" ")

$code = $tokens[0]

if ($code -eq 213)
{
    Write-Host "Timestamp is" $tokens[1]
}
else
{
    Write-Host "Error" $response
}

它会输出如下内容:

Timestamp is 20150709065036

现在解析它,并与本地文件的 UTC 时间戳进行比较:

(Get-Item "install_firefox.exe").LastWriteTimeUtc

或者节省一些时间,使用可以为您完成此操作的 FTP library/tool。

例如WinSCP .NET assembly, you can synchronize whole remote folder with installers with a local copy with one call to the Session.SynchronizeDirectories。或者您可以将同步限制为仅单个文件。

# Load WinSCP .NET assembly
Add-Type -Path "WinSCPnet.dll"

# Setup session options
$sessionOptions = New-Object WinSCP.SessionOptions
$sessionOptions.Protocol = [WinSCP.Protocol]::Ftp
$sessionOptions.HostName = "ftpsite.com"

$session = New-Object WinSCP.Session

# Connect
$session.Open($sessionOptions)

$transferOptions = New-Object WinSCP.TransferOptions
# Synchronize only this one file.
# If you remove the file mask, all files in the folder are synchronized:
$transferOptions.FileMask = "install_firefox.exe"

$session.SynchronizeDirectories(
    [WinSCP.SynchronizationMode]::Local, "$dir\Apps", "/folder",
    $False, $False, [WinSCP.SynchronizationCriteria]::Time, 
    $transferOptions).Check()

要使用程序集,只需将 .NET assembly package 的内容提取到您的脚本文件夹中。不需要其他安装。

程序集不仅支持 MDTM,还支持其他检索时间戳的替代方法。

另请参阅显示上述代码和其他技术的 related Powershell example

(我是WinSCP的作者)