简单的Powershell脚本从FTP

时间:2016-05-25 18:54:59

标签: powershell ftp

所以我一直试图弄清楚这个脚本,试图将每日文件上传到我们的FTP服务器。我过去使用过这个脚本是成功的,因为文件是以一致的文件名上传的: IE:FILE_NAME_2016-05-25.csv(当前日期的日期总是这样格式化)

因此,当文件名保持这种一致性时,这是有效的,但我需要使用它来获取一个附加到末尾的值不一致的文件。 IE:FILE_NAME_2016-05-25_0503(最后一个值永远不会一致)。

那么有没有办法在文件/文件夹变量的末尾使用通配符来解释这个?

我的代码(注意我对powershell很新)

#Get's file from the FTP using today's date
Write-Host "Please wait while your file downloads"
$server = "ftp.server.net" 
$user = "user"
$pass = "pass"
$invocation = (Get-Variable MyInvocation).Value
$localpath = Split-Path $invocation.MyCommand.Path
$TodayDate = (get-date)
$FileNameDate = date $TodayDate -f yyyy-MM-dd
$remotefilepath = "inbox/sub1/sub2/FILE_NAME_$FileNameDate_[*].txt"
$localfilename = "FILE_NAME_$FileNameDate.csv"
$localfilelocation = "$localpath\$localfilename"
$webclient = New-Object System.Net.WebClient
$webclient.Credentials = New-Object System.Net.NetworkCredential($user, $pass)
$uri = New-Object System.Uri(“ftp://$server/$remotefilepath”)
$webclient.DownloadFile($uri, $localfilelocation)

我试图在最后使用通配符,但看起来我做错了

2 个答案:

答案 0 :(得分:1)

我会看一下使用WinSCP's .Net library,它提供了一套更完整的FTP命令。或者您可以使用FtpWebRequest,它还提供您正在寻找的功能,因为您可以枚举远程文件然后获取所需的功能,但由于所有数据传输都是流,因此可能使用起来更麻烦。 C#代码对PowerShell来说非常便携,但对于新手来说可能有点陡峭,所以你可能想要坚持使用WinSCP的.Net库。

另一种方法是构建一个脚本文件并使用ftp.exe来获取它。 Here是一个旧文档,告诉您该怎么做。您将要使用mget命令。一个缺点是您必须将密码写入文本文件,但是,从技术上讲,您已经这样做了,因为它在您的PowerShell脚本中。你可以这样做:

Set-Content -Path $FtpScriptFile -Encoding ASCII -Value "open ""ftp://$server/$remotefilepath"""
Add-Content -Path $FtpScriptFile -Encoding ASCII -Value "$user"
Add-Content -Path $FtpScriptFile -Encoding ASCII -Value "$pass"
Add-Content -Path $FtpScriptFile -Encoding ASCII -Value "cd ""inbox/sub1/sub2/"""
Add-Content -Path $FtpScriptFile -Encoding ASCII -Value "lcd ""$localpath"""
Add-Content -Path $FtpScriptFile -Encoding ASCII -Value "bin"
Add-Content -Path $FtpScriptFile -Encoding ASCII -Value "mget ""FILE_NAME_$FileNameDate_[*].txt"""
Add-Content -Path $FtpScriptFile -Encoding ASCII -Value "bye"
C:\Windows\System32\ftp.exe -s:"$FtpScriptFile"

(注意:我根本没有测试过,这不一定是最好的方法。)

此外,您的许多脚本都可以进行优化。你正在做一些后空翻来获得一些简单的值。 (Get-Variable MyInvocation).Value$MyInvocation相同。您可能需要获取变量的唯一原因是列出已分配的变量并使用动态变量 - 即,直到运行时才知道名称的变量...变量变量名称。

此:

$invocation = (Get-Variable MyInvocation).Value
$localpath = Split-Path $invocation.MyCommand.Path
$TodayDate = (get-date)
$FileNameDate = date $TodayDate -f yyyy-MM-dd

可以是:

$LocalPath = Split-Path $MyInvocation.MyCommand.Path
$FileNameDate = Get-Date -Format 'yyyy-MM-dd'

我也想知道这是否是导致你出现问题的原因:

$remotefilepath = "inbox/sub1/sub2/FILE_NAME_$FileNameDate_[*].txt"

当我在PowerShell ISE中使用它时,看起来系统认为变量是$FileNameDate_。尝试:

$remotefilepath = "inbox/sub1/sub2/FILE_NAME_$($FileNameDate)_[*].txt"

这就是大多数人写的。

就个人而言,我可能会像这样编写你的脚本:

$RemoteFilePath = 'inbox/sub1/sub2/FILE_NAME_{0}_[*].txt' -f $FileNameDate
$LocalFileName = 'FILE_NAME_{0}.csv' -f $FileNameDate
$LocalFileLocation = Join-Path -Path $LocalPath -ChildPath $LocalFileName

使用格式运算符(请参阅Get-Help about_Operators -ShowWindow)和Join-Path cmdlet。我发现它更容易阅读。

答案 1 :(得分:1)

嗨,请尝试这个(可以修剪很多,但它应该工作:))。

Write-Host "Please wait while your file downloads"

#Function to get all files
function Get-FtpDir ($url,$credentials)
{
    $request = [Net.WebRequest]::Create($url)
    $request.Credentials = $credentials
    $request.Method = [System.Net.WebRequestMethods+FTP]::ListDirectory
    $response = $request.GetResponse()
    $reader = New-Object IO.StreamReader $response.GetResponseStream()
    $readline = $reader.ReadLine()
    $output = New-Object System.Collections.Generic.List[System.Object]
    while ($readline -ne $null)
    {
        $output.Add($readline)
        $readline = $reader.ReadLine()
    }
    $reader.Close()
    $response.Close()
    $output
}

$server = "ftp.server.net"
$user = "user"
$pass = "pass"
$invocation = (Get-Variable MyInvocation).Value
$localpath = Split-Path $invocation.MyCommand.Path
$TodayDate = (get-date)
$FileNameDate = date $TodayDate -f yyyy-MM-dd
$remotefilepath = "inbox/sub1/sub2"
$localfilename = "FILE_NAME_$FileNameDate.csv"
$localfilelocation = "$localpath\$localfilename"
$uri = New-Object System.Uri(“ftp://$server/$remotefilepath”)

#List of all files on FTP-Server
$files = Get-FTPDir $uri -credentials (New-Object System.Net.NetworkCredential($user, $pass))

foreach ($file in $files)
{
    if ($file -like "FILE_NAME_$($FileNameDate)_*.txt")
    {
        $file
        $fileuri = New-Object System.Uri(“ftp://$server/$remotefilepath/$file”)
        $webclient = New-Object System.Net.WebClient
        $webclient.Credentials = New-Object System.Net.NetworkCredential($user, $pass)
        $webclient.DownloadFile($fileuri, $localfilelocation)
    }
}