Differences
This shows you the differences between the selected revisions of the page.
2013-01-18 | 2013-01-23 | ||
no summary (62.38.54.57) (hidden) | ssh root@192.168.1.11 (188.176.170.253) (hidden) | ||
Line 25: | Line 25: | ||
</code> | </code> | ||
+ | |||
+ | ===== [[download_timestamped_filename]] Downloading file to timestamped-filename ===== | ||
+ | |||
+ | ===== Level 2 Headline ===== | ||
+ | |||
+ | &deprecated_use_net | ||
+ | |||
+ | You may use following [[guide_automation_advanced#wsh|Windows script host JavaScript code]] (''example.js''): | ||
+ | |||
+ | <code javascript> | ||
+ | // Local path to download to (keep trailing slash) | ||
+ | var LOCALPATH = ".\\"; | ||
+ | // Remote path to download from (keep trailing slash) | ||
+ | var REMOTEPATH = "/"; | ||
+ | // File to download | ||
+ | var FILE = "winscp421.exe"; | ||
+ | // Session to connect to | ||
+ | var SESSION = "test@127.0.0.1"; | ||
+ | // Path to winscp.com | ||
+ | var WINSCP = "c:\\program files\\winscp\\winscp.com"; | ||
+ | |||
+ | // helper function to pad zeroes to the left of number | ||
+ | function pad(n, len) | ||
+ | { | ||
+ | var s = n.toString(); | ||
+ | while (s.length < len) | ||
+ | { | ||
+ | s = '0' + s; | ||
+ | } | ||
+ | return s; | ||
+ | } | ||
+ | |||
+ | var date = new Date(); | ||
+ | |||
+ | // format timestamp | ||
+ | var stamp = | ||
+ | pad(date.getFullYear(), 4) + | ||
+ | pad(date.getMonth(), 2) + | ||
+ | pad(date.getDate(), 2) + | ||
+ | pad(date.getHours(), 2) + | ||
+ | pad(date.getMinutes(), 2) + | ||
+ | pad(date.getSeconds(), 2); | ||
+ | |||
+ | var shell = WScript.CreateObject("WScript.Shell"); | ||
+ | |||
+ | // run winscp to download the file into timestamped-filename | ||
+ | exec = shell.Exec("\"" + WINSCP + "\""); | ||
+ | exec.StdIn.Write( | ||
+ | "option batch abort\n" + | ||
+ | "open \"" + SESSION + "\"\n" + | ||
+ | "get \"" + REMOTEPATH + FILE + "\" \"" + LOCALPATH + FILE + "." + stamp + "\"\n" + | ||
+ | "exit\n"); | ||
+ | |||
+ | // wait until the script finishes | ||
+ | while (exec.Status == 0) | ||
+ | { | ||
+ | WScript.Sleep(100); | ||
+ | WScript.Echo(exec.StdOut.ReadAll()); | ||
+ | } | ||
+ | </code> | ||
+ | |||
+ | Run the script with command: | ||
+ | <code> | ||
+ | cscript /nologo example.js | ||
+ | </code> | ||
+ | |||
+ | ===== [[download_most_recent_file]] Downloading the most recent file ===== | ||
+ | &deprecated_use_net | ||
+ | |||
+ | You may use following [[guide_automation_advanced#wsh|Windows script host JavaScript code]] (''example.js''): | ||
+ | |||
+ | <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 + "\" /log=\"" + logfilepath + "\""); | ||
+ | exec.StdIn.Write( | ||
+ | "option batch abort\n" + | ||
+ | "open \"" + SESSION + "\"\n" + | ||
+ | "ls \"" + REMOTEPATH + FILEMASK + "\"\n" + | ||
+ | "exit\n"); | ||
+ | |||
+ | // wait until the script finishes | ||
+ | while (exec.Status == 0) | ||
+ | { | ||
+ | WScript.Sleep(100); | ||
+ | WScript.Echo(exec.StdOut.ReadAll()); | ||
+ | } | ||
+ | |||
+ | 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 the script finishes | ||
+ | while (!exec.StdOut.AtEndOfStream) | ||
+ | { | ||
+ | WScript.Echo(exec.StdOut.ReadAll()); | ||
+ | } | ||
+ | |||
+ | if (exec.ExitCode != 0) | ||
+ | { | ||
+ | WScript.Echo("Error downloading " + filenameLatest); | ||
+ | WScript.Quit(1); | ||
+ | } | ||
+ | </code> | ||
+ | |||
+ | Run the script with command: | ||
+ | <code> | ||
+ | cscript /nologo example.js | ||
+ | </code> | ||
+ | |||
+ | ===== [[checking_file_existence]] Checking file existence ===== | ||
+ | &deprecated_use_net | ||
+ | |||
+ | You may use following [[guide_automation_advanced#wsh|Windows script host JavaScript code]] (''example.js''): | ||
+ | |||
+ | <code javascript> | ||
+ | // Configuration | ||
+ | |||
+ | // Remote file search for | ||
+ | var FILEPATH = "/home/user/myfile.dat"; | ||
+ | // 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 p = FILEPATH.lastIndexOf('/'); | ||
+ | var path = FILEPATH.substring(0, p); | ||
+ | var filename = FILEPATH.substring(p + 1); | ||
+ | |||
+ | var exec; | ||
+ | |||
+ | // run winscp to check for file existence | ||
+ | exec = shell.Exec("\"" + WINSCP + "\" /log=\"" + logfilepath + "\""); | ||
+ | exec.StdIn.Write( | ||
+ | "option batch abort\n" + | ||
+ | "open \"" + SESSION + "\"\n" + | ||
+ | "ls \"" + path + "\"\n" + | ||
+ | "exit\n"); | ||
+ | |||
+ | // wait until the script finishes | ||
+ | while (exec.Status == 0) | ||
+ | { | ||
+ | WScript.Sleep(100); | ||
+ | WScript.Echo(exec.StdOut.ReadAll()); | ||
+ | } | ||
+ | |||
+ | if (exec.ExitCode != 0) | ||
+ | { | ||
+ | WScript.Echo("Error checking for file existence"); | ||
+ | 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/w:filename[@value='" + filename + "']"); | ||
+ | |||
+ | if (nodes.length > 0) | ||
+ | { | ||
+ | WScript.Echo("File found"); | ||
+ | // signalize file existence to calling process; | ||
+ | // you can also continue with processing (e.g. downloading the file) | ||
+ | // directly from the script here | ||
+ | WScript.Quit(0); | ||
+ | } | ||
+ | else | ||
+ | { | ||
+ | WScript.Echo("File not found"); | ||
+ | WScript.Quit(1); | ||
+ | } | ||
+ | </code> | ||
+ | |||
+ | Run the script with command: | ||
+ | <code> | ||
+ | cscript /nologo example.js | ||
+ | </code> | ||
+ | |||
+ | Following batch file shown how to continue with processing based on file exitence: | ||
+ | <code> | ||
+ | cscript /nologo example.js | ||
+ | if errorlevel 1 goto error | ||
+ | |||
+ | echo File exists, do something | ||
+ | rem Do something | ||
+ | exit | ||
+ | |||
+ | :error | ||
+ | echo Error or file not exists | ||
+ | </code> | ||
+ | |||
+ | Alternatively you can continue with the processing directly in JavaScript code as suggested by respective comments. | ||
+ | |||
+ | ===== [[local_move_after_successful_upload]] Moving local files to different location after successful upload ===== | ||
+ | &deprecated_use_net | ||
+ | |||
+ | WinSCP does not support move command for local files. Instead you can combine WinSCP script with batch file: | ||
+ | |||
+ | <code winscp> | ||
+ | option batch abort | ||
+ | option confirm off | ||
+ | # Connect | ||
+ | open mysession | ||
+ | # Upload the files | ||
+ | put *.* | ||
+ | </code> | ||
+ | |||
+ | Launch the above script from batch file like the one below: | ||
+ | |||
+ | <code> | ||
+ | winscp.com /script=example.txt | ||
+ | if errorlevel 1 goto error | ||
+ | |||
+ | echo Upload succeeded, moving local files | ||
+ | move *.* c:\backup\ | ||
+ | exit | ||
+ | |||
+ | :error | ||
+ | echo Upload failed, keeping local files | ||
+ | </code> | ||
+ | |||
+ | ===== [[synchronize_any_local_file]] Shortcut to synchronize any local directory with remote directory ===== | ||
+ | |||
+ | You may want to have script that synchronizes any local directory with a same-named subdirectory of fixed remote path, e.g.: | ||
+ | * ''c:\www\gallery'' with ''/home/user/www/gallery''; | ||
+ | * ''c:\documents and settings\username\www\forum'' with ''/home/user/www/forum''. | ||
+ | |||
+ | Such script is particularly useful for integrating with Windows Explorer's 'Send To' menu. | ||
+ | |||
+ | First create wrapper batch file to store the paths you want to synchronize into environment variables (change ''/home/user/www/'' to remote path root you want to synchronize against): | ||
+ | <code> | ||
+ | winscp.com /script=example.txt /parameter %1 "/home/user/www/%~n1%~x1" | ||
+ | </code> | ||
+ | |||
+ | The script ''example.txt'' may look like: | ||
+ | |||
+ | <code winscp> | ||
+ | # Being intended for interactive session, we are not enabling batch mode | ||
+ | # Connect | ||
+ | open mysession | ||
+ | # Synchronize paths provided via environment variables | ||
+ | synchronize remote "%1%" "%2%" | ||
+ | </code> | ||
+ | |||
+ | Then you can make a shortcut to the batch file: | ||
+ | * When placed on desktop, you can drop any local directory to it to start synchronization; | ||
+ | * When placed to ''c:\documents and settings\username\sendto'', you can use //Send To > Your Shortcut// from context menu of any local directory. | ||
+ | |||
+ | ===== [[auto_compress_download]] Automatically compress files before download ===== | ||
+ | Following script compresses selected files into tar/gzip archive and downloads it: | ||
+ | |||
+ | <code winscp> | ||
+ | option batch abort | ||
+ | option confirm off | ||
+ | open mysession | ||
+ | cd %1% | ||
+ | call tar -czf /tmp/archive.tar.gz %2% | ||
+ | lpwd | ||
+ | get -delete /tmp/archive.tar.gz | ||
+ | exit | ||
+ | </code> | ||
+ | |||
+ | Launch the above script from batch file like the one below, which automatically decompresses the archive: | ||
+ | |||
+ | <code> | ||
+ | winscp.com /script=example.txt /parameter %* | ||
+ | if errorlevel 1 goto error | ||
+ | |||
+ | echo Retrieving files succeeded | ||
+ | gzip -d archive.tar.gz | ||
+ | tar -xf archive.tar | ||
+ | del archive.tar | ||
+ | exit | ||
+ | |||
+ | :error | ||
+ | echo Retrieving files failed | ||
+ | </code> | ||
+ | |||
+ | Example of running the batch file to download all files under ''/home/user/www'': | ||
+ | |||
+ | <code> | ||
+ | example.bat /home/user/www *.* | ||
+ | </code> | ||
+ | |||
+ | The batch file needs Windows ports of ''gzip'' and ''tar'' tools. You can get them from [[http://sourceforge.net/projects/unxutils/|UnxUtils]] project. | ||
+ | |||
+ | ===== [[vbnet_robust_example]] Running WinSCP from VB.NET ===== | ||
+ | &deprecated_use_net | ||
+ | |||
+ | Following is more robust alternative to simple example contained in guide to [[guide_dotnet|SFTP file transfers in .NET]]. | ||
+ | |||
+ | <code vbnet> | ||
+ | Imports System | ||
+ | Imports System.IO | ||
+ | Imports System.Diagnostics | ||
+ | Imports System.Xml | ||
+ | Imports System.Xml.XPath | ||
+ | Imports System.Configuration.ConfigurationManager | ||
+ | |||
+ | Public Class SFTP | ||
+ | ' SFTP support, built on WinSCP | ||
+ | Public Shared Function PutSFTP(ByRef filename As String, ByRef remotehost As String, ByRef username As String, ByRef password As String, _ | ||
+ | Optional ByVal outfilename As String = Nothing, Optional ByVal output As String = Nothing, | ||
+ | Optional ByRef errmsg As String = Nothing) As Boolean | ||
+ | |||
+ | ' Run hidden WinSCP process | ||
+ | Dim winscp As Process = New Process() | ||
+ | Dim logname As String = Path.ChangeExtension(Path.GetTempFileName, "xml") | ||
+ | With winscp.StartInfo | ||
+ | ' SFTPExecutable needs to be defined in app.config to point to winscp.com | ||
+ | Try | ||
+ | .FileName = AppSettings("SFTPExecutable") | ||
+ | If .FileName Is Nothing OrElse .FileName.Length = 0 Then Throw (New Exception("from PutSFTP: SFTPExecutable not set in config file.")) | ||
+ | Catch ex As Exception | ||
+ | errmsg = ex.Message | ||
+ | Return False | ||
+ | End Try | ||
+ | .Arguments = "/log=" + logname | ||
+ | .UseShellExecute = False | ||
+ | .RedirectStandardInput = True | ||
+ | .RedirectStandardOutput = True | ||
+ | .CreateNoWindow = True | ||
+ | End With | ||
+ | Try | ||
+ | winscp.Start() | ||
+ | Catch ex As Exception | ||
+ | errmsg = "from PutSFTP: Could not run the WinSCP executable " & winscp.StartInfo.FileName & Environment.NewLine & ex.Message | ||
+ | Return False | ||
+ | End Try | ||
+ | |||
+ | ' Feed in the scripting commands | ||
+ | With winscp.StandardInput | ||
+ | .WriteLine("option batch abort") | ||
+ | .WriteLine("option confirm off") | ||
+ | .WriteLine("open sftp://" & username & ":" & password & "@" & remotehost) | ||
+ | If outfilename Is Nothing Then .WriteLine("put " & filename) Else .WriteLine("put " & filename & " """ & outfilename & """") | ||
+ | .Close() | ||
+ | End With | ||
+ | If Not output Is Nothing Then output = winscp.StandardOutput.ReadToEnd() | ||
+ | |||
+ | ' Wait until WinSCP finishes | ||
+ | winscp.WaitForExit() | ||
+ | |||
+ | ' Parse and interpret the XML log | ||
+ | ' (Note that in case of fatal failure the log file may not exist at all) | ||
+ | If Not File.Exists(logname) Then | ||
+ | errmsg = "from PutSFTP: The WinSCP executable appears to have crashed." | ||
+ | Return False | ||
+ | End If | ||
+ | |||
+ | Dim log As XPathDocument = New XPathDocument(logname) | ||
+ | Dim ns As XmlNamespaceManager = New XmlNamespaceManager(New NameTable()) | ||
+ | ns.AddNamespace("w", "http://winscp.net/schema/session/1.0") | ||
+ | Dim nav As XPathNavigator = log.CreateNavigator() | ||
+ | |||
+ | ' Success (0) or error? | ||
+ | Dim status As Boolean = (winscp.ExitCode = 0) | ||
+ | If Not status Then | ||
+ | errmsg = "from PutSFTP: There was an error transferring " & filename & "." | ||
+ | ' See if there are any messages associated with the error | ||
+ | For Each message As XPathNavigator In nav.Select("//w:message", ns) | ||
+ | errmsg &= Environment.NewLine & message.Value | ||
+ | Next message | ||
+ | End If | ||
+ | |||
+ | Try | ||
+ | My.Computer.FileSystem.DeleteFile(logname) | ||
+ | Catch ex As Exception | ||
+ | ' at least we tried to clean up | ||
+ | End Try | ||
+ | |||
+ | Return status | ||
+ | End Function | ||
+ | End Class | ||
+ | </code> | ||
+ | |||
+ | <trailer> | ||
+ | ===== Further Reading ===== | ||
+ | * Guide to [[guide_automation|scripting/automation]]. | ||
+ | * [[library|WinSCP .NET assembly]] | ||
+ | </trailer> | ||
+ | |||
+ | <nosplit> | ||
+ | ===== Other Examples ===== | ||
+ | * Guide to [[guide_automation|scripting/automation]]; | ||
+ | * Guide to [[guide_automation_advanced|advanced scripting]]; | ||
+ | * See [[library_examples|WinSCP .NET assembly examples]] for advanced tasks. | ||
+ | </nosplit> | ||
===== [[download_timestamped_filename]] Downloading file to timestamped-filename ===== | ===== [[download_timestamped_filename]] Downloading file to timestamped-filename ===== |