This is an old revision of the document!
Downloading the most recent file
Using WinSCP .NET Assembly
PowerShell
The following example uses WinSCP .NET assembly from a PowerShell script. If you have another preferred language, you can easily translate it.
param ( $localPath = "c:\downloaded\", $remotePath = "/home/user/" ) try { # Load WinSCP .NET assembly Add-Type -Path "WinSCPnet.dll" # Setup session options $sessionOptions = New-Object WinSCP.SessionOptions $sessionOptions.Protocol = [WinSCP.Protocol]::Sftp $sessionOptions.HostName = "example.com" $sessionOptions.UserName = "user" $sessionOptions.Password = "mypassword" $sessionOptions.SshHostKeyFingerprint = "ssh-rsa 2048 xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx" $session = New-Object WinSCP.Session try { # Connect $session.Open($sessionOptions) # Get list of files in the directory $directoryInfo = $session.ListDirectory($remotePath) # Select the most recent file $latest = $directoryInfo.Files | Where-Object { -Not $_.IsDirectory } | Sort-Object LastWriteTime -Descending | Select-Object -First 1 # Any file at all? if ($latest -eq $Null) { Write-Host "No file found" exit 1 } # Download the selected file $session.GetFiles($session.EscapeFileMask($remotePath + $latest.Name), $localPath).Check() } finally { # Disconnect, clean up $session.Dispose() } exit 0 } catch [Exception] { Write-Host $_.Exception.Message exit 1 }
C#
using System; using System.Linq; using WinSCP; class Program { static int Main(string[] args) { try { // Setup session options SessionOptions sessionOptions = new SessionOptions { Protocol = Protocol.Sftp, HostName = "example.com", UserName = "user", Password = "mypassword", SshHostKeyFingerprint = "ssh-rsa 2048 xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx", }; using (Session session = new Session()) { // Connect session.Open(sessionOptions); const string remotePath = "/home/user/"; const string localPath = "c:\\downloaded\\"; // Get list of files in the directory RemoteDirectoryInfo directoryInfo = session.ListDirectory(remotePath); // Select the most recent file RemoteFileInfo latest = directoryInfo.Files .Where(file => !file.IsDirectory) .OrderByDescending(file => file.LastWriteTime) .FirstOrDefault(); // Any file at all? if (latest == null) { throw new Exception("No file found"); } // Download the selected file session.GetFiles(session.EscapeFileMask(remotePath + latest.Name), localPath).Check(); } return 0; } catch (Exception e) { Console.WriteLine("Error: {0}", e); return 1; } } }
Using WinSCP Scripting
In the Beta Version
Use the -latest
switch of the get
command:
get -latest /home/user/* c:\downloaded\
In the Stable Version
You may use following Windows script host JScript code (example.js
):
// Configuration // Local path to download to (keep trailing slash) var LOCALPATH = "c:\\downloaded\\"; // Remote path to search in (keep trailing slash) var REMOTEPATH = "/home/user/"; // Mask of files to search for var FILEMASK = "*.*"; // Session to connect to var SESSION = "session"; // Path to winscp.com var WINSCP = "c:\\program files\\winscp\\winscp.com"; var filesys = WScript.CreateObject("Scripting.FileSystemObject"); var shell = WScript.CreateObject("WScript.Shell"); var logfilepath = filesys.GetSpecialFolder(2) + "\\" + filesys.GetTempName() + ".xml"; var exec; // run winscp to get list of file in the remote directory into XML log exec = shell.Exec("\"" + WINSCP + "\" /xmllog=\"" + logfilepath + "\""); exec.StdIn.Write( "option batch abort\n" + "open \"" + SESSION + "\"\n" + "ls \"" + REMOTEPATH + FILEMASK + "\"\n" + "exit\n"); // wait until it finishes and collect its output var output = exec.StdOut.ReadAll(); // optionally print the output WScript.Echo(output); if (exec.ExitCode != 0) { WScript.Echo("Error retrieving list of files"); WScript.Quit(1); } // look for log file var logfile = filesys.GetFile(logfilepath); if (logfile == null) { WScript.Echo("Cannot find log file"); WScript.Quit(1); } // parse XML log file var doc = new ActiveXObject("MSXML2.DOMDocument"); doc.async = false; doc.load(logfilepath); doc.setProperty("SelectionNamespaces", "xmlns:w='http://winscp.net/schema/session/1.0'"); var nodes = doc.selectNodes("//w:file"); // find the latest file var filenameLatest = null; var modificationLatest = null; for (var i = 0; i < nodes.length; ++i) { var filename = nodes[i].selectSingleNode("w:filename/@value"); var modification = nodes[i].selectSingleNode("w:modification/@value"); if ((filename != null) && (filename.value != ".") && (filename.value != "..") && (modification != null)) { // can compare timestamps stringwise if ((modificationLatest == null) || (modificationLatest < modification.value)) { modificationLatest = modification.value; filenameLatest = filename.value; } } } // no file in the log if (filenameLatest == null) { WScript.Echo("No file found"); WScript.Quit(0); } // run winscp to download the latest file exec = shell.Exec("\"" + WINSCP + "\""); exec.StdIn.Write( "option batch abort\n" + "option confirm off\n" + "open \"" + SESSION + "\"\n" + "get \"" + REMOTEPATH + filenameLatest + "\" \"" + LOCALPATH + "\"\n" + "exit\n"); // wait until it finishes and collect its output var output = exec.StdOut.ReadAll(); // optionally print the output WScript.Echo(output); if (exec.ExitCode != 0) { WScript.Echo("Error downloading " + filenameLatest); WScript.Quit(1); }
Run the script with command:
cscript /nologo example.js
Alternatives
Some of following alternatives can be easier to implement or actually even more appropriate for your specific task:
- Synchronizing a remote directory to a local directory (using
synchronize local
in scripting orSession.SynchronizeDirectories(SynchronizationMode.Local, …)
in .NET assembly); - Downloading all files created in the last 24 hours (using file mask
*>=1D
; e.g.get -filemask="*>=1D" /home/user/*
, or an equivalent in .NET assembly). - Downloading all files created today (using
%TIMESTAMP%
syntax to format file mask with today’s time constraint, e.g.get -filemask="*>=%TIMESTAMP#yyyy-mm-dd%" /home/user/*
, or an equivalent in .NET assembly).