Search code examples
batch-fileftpwinscp

Command line on Windows to get latest files from FTP site


I need a batch scripts run from command line on Windows, which downloads latest files from FTP site (the latest files might have more than a files sometimes).

I have used the following command from WinSCP.com but I only get one latest file. Can give me some direction?

get -latest *.txt

Wxample: with above command I only get filename XYZ.txt file only, I wish have a scripts manage to get both ABC.txt and ZZZ.txt.

filename        last written date
------------    ----------------------
ABC.txt         2016-01-01
ZZZ.txt         2016-01-01
A123.txt        2015-12-10

Solution

  • There's no built-in command to download multiple files based on date, we'll have to do it manually.

    The standard ls output is human-readable but not sortable by date:

    D---------   0                           0 Aug 21 15:32:37 2016 Default
    

    We'll need an xml log using /xmllog= parameter:

    <?xml version="1.0" encoding="UTF-8"?>
    <session xmlns="........." name="USER@localhost" start="2016-08-23T15:41:10.708Z">
      <ls>
        <destination value="/temp" />
        <files>
          <file>
            <filename value=".." />
            <type value="D" />
            <modification value="1899-12-30T02:00:00.000Z" />
            <permissions value="---------" />
          </file>
    

    Good, each file has a machine-readable date, name, type (D for directory, we'll skip them).


    The batch file.
    (comment separators are also part of code)

    @echo off
    

    : Setup

    setlocal enableDelayedExpansion
    set "WinSCP=C:\somepath\WinSCP.com"
    set "ftp=ftp://USER:[email protected]"
    set "remoteFolder=/someFolderNoTrailingSlash"
    

    : List all ftp files

    "%WinSCP%" ^
        /command "open %ftp%" "ls ""%remoteFolder%""" "exit" ^
        /xmllog="%temp%\ftplog.xml" >nul
    (
        set isDirectory=
        for /f "tokens=1,3 delims=<= " %%a in ('type "%temp%\ftplog.xml"') do (
            if "%%a"=="filename"     (set "line=%%~b" & set isDirectory=)
            if "%%a"=="type" if "%%~b"=="D" (set isDirectory=yes)
            if "%%a"=="modification" if not defined isDirectory (
                set "line=%%~b*!line!"
                echo !line!
            )
        )
    ) > "%temp%\ftplist.txt"
    

    : Sort by date and make a WinSCP script to get the latest files with same date

    set lastDate=
    (
        echo open %ftp%
        for /f "delims=* tokens=1,2" %%a in ('
            sort /reverse "%temp%\ftplist.txt"
        ') do (
            for /f "delims=T" %%c in ("%%a") do set thisDate=%%c
            if defined lastDate (
                if not !thisDate!==!lastDate! goto download
            ) else (
                set lastDate=!thisDate!
            )
            echo get -preservetime "%remoteFolder%/%%b"
        )
    ) > "%temp%\ftpscript.txt"
    if not defined lastDate goto cleanup
    

    : Download and cleanup temporary files

    :download
    "%WinSCP%" /script="%temp%\ftpscript.txt" /command "exit"
    
    :cleanup
    del "%temp%\ftplog.xml" "%temp%\ftplist.txt" "%temp%\ftpscript.txt"
    
    pause