Mengunduh file kemarin di PowerShell menggunakan WinSCP

1

Lingkup Desain: Gunakan unit PowerShell dan WinSCP .NET untuk mengotomatisasi pengunduhan malam dengan menggunakan cap waktu file untuk mengidentifikasi file yang akan diunduh. Server FTP yang terhubung adalah IIS sehingga tidak mendukung semua perintah seperti MLSD dalam konfigurasi saat ini dan saya tidak melihat mereka melakukan perubahan jika diminta.

Masalah: File yang memiliki 1 atau 2 digit bulan menghasilkan panjang string yang berbeda sehingga saya tidak yakin bagaimana cara menyiasatinya. Kode saya berfungsi sekarang, tetapi akan berhenti bekerja pada bulan Oktober.

misal Maret menampilkan 3 / dd / yyyy bukannya 03 / dd / yyyy

Catatan lain: Awalnya saya mencoba membuat skrip ini menggunakan WinSCP.com, tetapi saya tidak dapat menemukan cara untuk menentukan tanggal dengan benar.

misalnya Anda dapat menentukan *.zip>=1Datau *.zip<=1D, tetapi saat ini *.zip=1Datau *.zip==1Dtidak didukung dengan rilis terbaru WinSCP.

Kode:

$yesterday = [DateTime]::Today.AddDays(-1).ToString("M/dd/yyyy")
# OR I have to use ToString("MM/dd/yyyy") for months 10-12,
# but I need both formats to work.
#delete the temporary file
del .\FTPfiles.txt
# Load WinSCP .NET assembly
Add-Type -Path "C:\Program Files (x86)\WinSCP\WinSCPnet.dll"

# Setup session options
$sessionOptions = New-Object WinSCP.SessionOptions -Property @{
    Protocol = [WinSCP.Protocol]::Ftp
    HostName = "server.com"
    UserName = "joe"
    Password = "smith"
}

$session = New-Object WinSCP.Session

    try
    {
        # Connect
        $session.Open($sessionOptions)

        $directory = $session.ListDirectory("/Folder")

        foreach ($fileInfo in $directory.Files)
        {
            Write-Output ("{1} {0}" -f
                $fileInfo.Name, $fileInfo.LastWriteTime) >> FTPfiles.txt
        }
        $fileList = get-content .\FTPfiles.txt | findstr $yesterday
        $stripped = $fileList -creplace '^.*Z12', 'Z12'


        # Download files
        $remotePath = "/Folder/"
        $transferOptions = New-Object WinSCP.TransferOptions
        $transferOptions.TransferMode = [WinSCP.TransferMode]::Binary

        $lines = $stripped

        foreach ($line in $lines)
        {
            Write-Host ("Downloading {0} ..." -f $line)
            $session.GetFiles($remotePath+$line, "C:\Downloads\").Check()
        }

    }


catch [Exception]
{
    Write-Host ("Error: {0}" -f $_.Exception.Message)
    exit 1
}
finally
{
    # Disconnect, clean up
    $session.Dispose()
} 

The $fileInfo in $directory.Filesmenulis waktu terakhir menulis dan kemudian mengajukan nama ke FTPfiles.txtuntuk semua file yang terdapat pada server FTP dari folder tertentu. File teks ini kemudian dibaca dan kemudian dikurangi menjadi hanya file yang memiliki waktu tulis yang terjadi pada tanggal kemarin, yang saat ini hanya berfungsi 9 bulan dalam setahun karena format tanggal menggunakan 1 digit untuk bulan alih-alih 2 digit .

Selanjutnya file tersebut dibaca dan dihapus tanggalnya sebelum nama file sehingga nama file tersebut akan digunakan untuk mengulang untuk mengunduh. Transformasinya terlihat seperti ini:

FROM:
3/14/2017 2:04:00 AM Z1234_20170314050001_1.zip
3/14/2017 3:04:00 AM Z1234_20170315060002_1.zip
3/14/2017 4:04:00 AM Z1234_20170316070001_1.zip
3/14/2017 5:04:00 AM Z1234_20170317080001_1.zip

TO:
Z1234_20170314050001_1.zip
Z1234_20170315060002_1.zip
Z1234_20170316070001_1.zip
Z1234_20170317080001_1.zip

Kemudian skrip menggunakan nama file tersebut untuk mengunduh file yang dibutuhkan dari hari sebelumnya.

Brad
sumber
2
Saya tidak melihat masalah ATM, formatnya [DateTime]::Today.AddDays(-1).ToString("M/dd/yyyy")akan melebar ke dua digit bulan pada bulan Oktober, yang satu M berarti tidak ada yang memimpin nol?
Lotings
@LotPings benar: mis. [DateTime]::Today.AddDays(-120).ToString("M/dd/yyyy")Mengembalikan (cca empat bulan lalu tanggal) 11/15/2016dengan dua digit bulan. BTW, Anda tidak perlu membuat file sementara dan menggunakan findstr.exealat eksternal . Anda dapat mengecek $fileInfo.LastWriteTime langsung di PowerShell menggunakan regex dan -matchoperator yang sesuai ...
JosefZ
@LotPings sudah benar, pemformatan string .NET akan menangani itu dengan baik. [datetime]::Now.AddDays(200).ToString("M/dd/yyyy")akan memverifikasi (saat ini menempatkan Anda ke Oktober atau menggunakan format string MM untuk selalu mendapatkan 2 digit
Austin T French

Jawaban:

1

Coba fungsi ini dan berikan rentang tanggal yang Anda tentukan dalam parameter StartDatedanEndDate

Function Download-Files 
{ 
    [CmdletBinding()] 
    Param 
    ( 
        [Parameter(Mandatory=$true)][Object]$Session, 
        [Parameter(Mandatory=$true)][String]$RemotePath, 
        [Parameter(Mandatory=$true)][String]$LocalPath, 
        [Parameter(Mandatory=$false)][String]$StartDate, 
        [Parameter(Mandatory=$false)][String]$EndDate 
    ) 

    If (-Not (Test-Path -Path $LocalPath -PathType Container)) { 
        New-Item -Path $LocalPath -ItemType Directory 
    } 

    Get-WinSCPChildItem -WinSCPSession $Session -Path $RemotePath | ForEach-Object { 
        If (-not($_.IsThisDirectory) -and -not($_.IsParentDirectory) -and $_.IsDirectory) { 
            Download-Files -Session $Session -RemotePath "$RemotePath\$($_.Name)\" -LocalPath "$LocalPath\$($_.Name)\" -StartDate $StartDate -EndDate $EndDate 
        } 

        If (-not($_.IsDirectory)) { 
            If ($_.LastWriteTime -ge $StartDate -and $_.LastWriteTime -le $EndDate) { 
                Receive-WinSCPItem -WinSCPSession $Session -Path "$RemotePath\$($_.Name)" -Destination $LocalPath 
            } 
        } 
    } 
}

Anda dapat mengunduh contoh kode lengkap dari Cara mengunduh file terbaru di PowerShell oleh WinSCP

Eric
sumber
1

Anda dapat menggunakan todaydan yesterdaykata kunci untuk kendala waktu atas dan bawah dalam satu file mask WinSCP :

$transferOptions = New-Object WinSCP.TransferOptions
$transferOptions.FileMask = "*>=yesterday<today"
$session.GetFiles("/Folder/*",  "C:\Downloads\", $False, $transferOptions).Check()

Ini membutuhkan WinSCP 5.15 dan yang lebih baru.


Di versi WinSCP yang lebih lama, Anda dapat membuat cap waktu di kode PowerShell Anda, seperti:
*>=2017-03-15<2017-03-16

(waktu tengah malam tersirat, itu juga mengapa *=2017-03-15tidak, apa yang Anda inginkan; dan juga alasan mengapa itu tidak diterapkan, karena tidak akan ada gunanya)

Di PowerShell, Anda bisa menerapkannya seperti:

$yesterday = (Get-Date).AddDays(-1)
$yesterday_timestamp = $yesterday.ToString("yyyy-MM-dd")
$today = Get-Date
$today_timestamp = $today.ToString("yyyy-MM-dd")

$transferOptions = New-Object WinSCP.TransferOptions
$file_mask = "*>=$yesterday_timestamp<$today_timestamp"
$transferOptions.FileMask = $file_mask

$session.GetFiles("/Folder/*",  "C:\Downloads\", $False, $transferOptions).Check()

Lihat artikel WinSCP tentang memformat stempel waktu di PowerShell .

Meskipun Anda juga dapat menggunakan sintaks WinSCP%TIMESTAMP% untuk implementasi yang lebih sederhana:

$transferOptions = New-Object WinSCP.TransferOptions
$transferOptions.FileMask = "*>=%TIMESTAMP-1D#yyyy-mm-dd%<%TIMESTAMP#yyyy-mm-dd%"
$session.GetFiles("/Folder/*",  "C:\Downloads\", $False, $transferOptions).Check()

Lihat artikel WinSCP tentang Mengunduh file terbaru .

Martin Prikryl
sumber
Ketika saya menggunakan $ session.GetFiles ("/ Folder / *" itu juga mengunduh folder anak secara berulang. Bagaimana saya bisa mengecualikan folder?
Brad
Saya dapat memfilter ke * .zip yang berfungsi, tetapi jika saya membutuhkan semuanya dari folder yang ditentukan tanpa menjadi rekursif, bagaimana saya bisa mengecualikan ini?
Brad