Differences
This shows you the differences between the selected revisions of the page.
2015-08-25 | 2015-08-25 | ||
no summary (martin) (hidden) | Restored revision 1435092494. Undoing revision 1440530835. (martin) (hidden) | ||
Line 6: | Line 6: | ||
<code powershell> | <code powershell> | ||
param ( | param ( | ||
- | $session = "sftp://user:mypassword;fingerprint=ssh-rsa-xx-xx-xx@example.com/", | + | $localPath = "c:\downloaded\", |
- | $remotePath = "/path", | + | $remotePath = "/home/user/" |
- | $outFile = "listing.csv" | + | |
) | ) | ||
Line 18: | Line 17: | ||
# Setup session options | # Setup session options | ||
$sessionOptions = New-Object WinSCP.SessionOptions | $sessionOptions = New-Object WinSCP.SessionOptions | ||
- | $sessionOptions.ParseUrl($session) | + | $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 | try | ||
{ | { | ||
# Connect | # Connect | ||
- | Write-Host "Connecting..." | ||
- | $session = New-Object WinSCP.Session | ||
$session.Open($sessionOptions) | $session.Open($sessionOptions) | ||
+ | |||
+ | # Get list of files in the directory | ||
+ | $directoryInfo = $session.ListDirectory($remotePath) | ||
- | # Retrieve listing | + | # Select the most recent file |
- | Write-Host "Listing..." | + | $latest = |
- | ·······$directory = $session.ListDirectory($remotePath) | + | ···········$directoryInfo.Files | |
+ | ············Where-Object { -Not $_.IsDirectory } | | ||
+ | ············Sort-Object LastWriteTime -Descending | | ||
+ | ············Select-Object -First 1 | ||
- | # Remove output file if it exists | + | # Any file at all? |
- | if (Test-Path $outFile) | + | if ($latest -eq $Null) |
{ | { | ||
- | Remove-Item $outFile | + | Write-Host "No file found" |
- | ········} | + | ···········exit 1 |
- | + | ||
- | # Generate a custom listing for ach file in the output file | + | |
- | # Using UTF-16 (Unicode) encoding that Microsoft Excel likes. | + | |
- | foreach ($fileInfo in $directory.Files) | + | |
- | { | + | |
- | ("`"{0}`"`t{1}`t`"{2}`"" -f $fileInfo.Name, $fileInfo.Length, $fileInfo.LastWriteTime) | Out-File -Append $outFile -Encoding Unicode | + | |
} | } | ||
- | Write-Host "Done" | + | # Download the selected file |
+ | $session.GetFiles($session.EscapeFileMask($remotePath + $latest.Name), $localPath).Check() | ||
} | } | ||
finally | finally | ||
Line 62: | Line 66: | ||
===== [[scripting]] Using WinSCP Scripting ===== | ===== [[scripting]] Using WinSCP Scripting ===== | ||
- | You may have WinSCP produce [[logging_xml|XML log]] with the listing and convert it to your custom format [[logging_xml#xslt|using XSLT]]: | + | You may use following [[guide_automation_advanced#wsh|Windows script host JScript code]] (''example.js''): |
- | Use the following Windows batch file (''listing.bat''): | + | <code javascript> |
+ | // 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); | ||
+ | } | ||
+ | </code> | ||
+ | |||
+ | Run the script with command: | ||
<code batch> | <code batch> | ||
- | @echo off | + | cscript /nologo example.js |
- | set XMLLOG=script.xml | + | |
- | winscp.com /log=script.log /xmllog=%XMLLOG% /command ^ | + | |
- | "open mysession" ^ | + | |
- | "ls /path" ^ | + | |
- | "exit" | + | |
- | if %ERRORLEVEL% == 0 msxsl.exe %XMLLOG% listing.xsl > listing_script.csv | + | |
</code> | </code> | ||
- | Where the ''listing.xsl'' may look like: | + | ===== Alternatives ===== |
- | <code xml> | + | Some of following alternatives can be easier to implement or actually even more appropriate for your specific task: |
- | <?xml version="1.0" encoding="UTF-8"?> | + | |
- | <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:winscp="http://winscp.net/schema/session/1.0"> | + | ··* Synchronizing a remote directory to a local directory (using ''[[scriptcommand_synchronize|synchronize local]]'' in scripting or ''[[library_session_synchronizedirectories|Session.SynchronizeDirectories(SynchronizationMode.Local, ...)]]'' in .NET assembly); |
- | ···<!-- Using UTF-16 encoding that Microsoft Excel likes --> | + | ·* Downloading all files created in the last 24 hours (using [[file_mask|file mask]] ''*>=1D''; e.g. ''%%get -filemask="*>=1D" /home/user/*%%'', or an equivalent in .NET assembly). |
- | ···<xsl:output method="text" encoding="UTF-16"/> | + | ·* Downloading all files created today (using ''[[scripting#timestamp|%TIMESTAMP%]]'' syntax to format [[file_mask|file mask]] with today's time constraint, e.g. ''%%get -filemask="*>=%TIMESTAMP#yyyy-mm-dd%"·/home/user/*%%'', or an equivalent in .NET assembly). |
- | ···<xsl:strip-space elements="*"/> | + | |
- | <xsl:template match='winscp:ls[winscp:result[@success="true"]]/winscp:files/winscp:file'> | + | |
- | ········<xsl:text>"</xsl:text> | + | |
- | ········<xsl:value-of select="winscp:filename/@value"/> | + | |
- | ········<xsl:text>"	</xsl:text> | + | |
- | ········<xsl:value-of select="winscp:size/@value"/> | + | |
- | ········<xsl:text>	"</xsl:text> | + | |
- | <xsl:value-of select="winscp:modification/@value"/> | + | |
- | ·········<xsl:text>&quot;
</xsl:text> | + | |
- | </xsl:template> | + | |
- | </xsl:stylesheet> | + | |
- | </code> | + | |
===== Further Reading ===== | ===== Further Reading ===== | ||
Line 100: | Line 194: | ||
* Guide to [[guide_automation|scripting/automation]]; | * Guide to [[guide_automation|scripting/automation]]; | ||
* [[library|WinSCP .NET assembly]]; | * [[library|WinSCP .NET assembly]]; | ||
- | * [[library_powershell|Using WinSCP .NET Assembly from PowerShell]]; | + | * [[library_powershell|Using WinSCP .NET Assembly from PowerShell]]. |
- | * [[logging_xml|XML logging]]. | + | |