Differences
This shows you the differences between the selected revisions of the page.
2015-06-23 | 2015-08-25 | ||
no summary (martin) | no summary (martin) (hidden) | ||
Line 6: | Line 6: | ||
<code powershell> | <code powershell> | ||
param ( | param ( | ||
- | $localPath = "c:\downloaded\", | + | $session = "sftp://user:mypassword;fingerprint=ssh-rsa-xx-xx-xx@example.com/", |
- | $remotePath = "/home/user/" | + | $remotePath = "/path", |
+ | $outFile = "listing.csv" | ||
) | ) | ||
Line 17: | Line 18: | ||
# Setup session options | # Setup session options | ||
$sessionOptions = New-Object WinSCP.SessionOptions | $sessionOptions = New-Object WinSCP.SessionOptions | ||
- | $sessionOptions.Protocol = [WinSCP.Protocol]::Sftp | + | $sessionOptions.ParseUrl($session) |
- | $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) | ||
- | # Select the most recent file | + | # Retrieve listing |
- | $latest = | + | Write-Host "Listing..." |
- | ···········$directoryInfo.Files | | + | ·······$directory = $session.ListDirectory($remotePath) |
- | ············Where-Object { -Not $_.IsDirectory } | | + | |
- | ············Sort-Object LastWriteTime -Descending | | + | |
- | ············Select-Object -First 1 | + | |
- | # Any file at all? | + | # Remove output file if it exists |
- | if ($latest -eq $Null) | + | if (Test-Path $outFile) |
{ | { | ||
- | Write-Host "No file found" | + | Remove-Item $outFile |
- | ···········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 | ||
} | } | ||
- | # Download the selected file | + | Write-Host "Done" |
- | $session.GetFiles($session.EscapeFileMask($remotePath + $latest.Name), $localPath).Check() | + | |
} | } | ||
finally | finally | ||
Line 66: | Line 62: | ||
===== [[scripting]] Using WinSCP Scripting ===== | ===== [[scripting]] Using WinSCP Scripting ===== | ||
- | You may use following [[guide_automation_advanced#wsh|Windows script host JScript code]] (''example.js''): | + | You may have WinSCP produce [[logging_xml|XML log]] with the listing and convert it to your custom format [[logging_xml#xslt|using XSLT]]: |
- | <code javascript> | + | Use the following Windows batch file (''listing.bat''): |
- | // 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> | ||
- | cscript /nologo example.js | + | @echo off |
+ | 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> | ||
- | ===== Alternatives ===== | + | Where the ''listing.xsl'' may look like: |
- | Some of following alternatives can be easier to implement or actually even more appropriate for your specific task: | + | <code xml> |
- | + | <?xml version="1.0" encoding="UTF-8"?> | |
- | ··* 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); | + | <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:winscp="http://winscp.net/schema/session/1.0"> |
- | * 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). | + | ···<!-- Using UTF-16 encoding that Microsoft Excel likes --> |
- | ·* Downloading all files created today (using ''[[scripting#timestamp|%TIMESTAMP%]]039;' syntax to format [[file_mask|file mask]] with today's time constraint, e.g. '039;%%get -filemask="*>=%TIMESTAMP#yyyy-mm-dd%" /home/user/*%%'', or an equivalent in .NET assembly). | + | ···<xsl:output method="text" encoding="UTF-16"/> |
+ | ····<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>&quot;&#9;</xsl:text> | ||
+ | ········<xsl:value-of select="winscp:size/@value"/> | ||
+ | ········<xsl:text>&#9;&quot;</xsl:text> | ||
+ | <xsl:value-of select="winscp:modification/@value"/> | ||
+ | ·········<xsl:text>&quot;
</xsl:text> | ||
+ | </xsl:template> | ||
+ | </xsl:stylesheet> | ||
+ | </code> | ||
===== Further Reading ===== | ===== Further Reading ===== | ||
Line 194: | Line 100: | ||
* 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]]. | ||