Differences
This shows you the differences between the selected revisions of the page.
scripts 2014-11-21 | scripts 2021-03-31 (current) | ||
Line 1: | Line 1: | ||
====== Useful Scripts ====== | ====== Useful Scripts ====== | ||
- | ~~SPLIT~~ | ||
- | ===== [[upload_single_file]] Uploading a single file ===== | + | ··* [[script_upload_single_file|*]] |
- | A single file upload involves so few commands that it is enough to provide them on the command line, saving writing a script file: | + | ··* [[script_upload_multiple_servers|*]] |
+ | * [[script_download_timestamped_filename|*]] | ||
+ | * [[script_download_most_recent_file|*]] | ||
+ | ··* [[script_upload_most_recent_file|*]] | ||
+ | * [[script_checking_file_existence|*]] | ||
+ | * [[script_local_move_after_successful_upload|*]] | ||
+ | * [[script_locking_files_while_uploading|*]] | ||
+ | * [[script_downloading_when_done_file_exists|*]] | ||
+ | * [[script_download_files_to_same_folder|*]] | ||
+ | * [[script_upload_file_list|*]] | ||
+ | * [[script_synchronize_any_local_file|*]] | ||
+ | * [[script_auto_compress_download|*]] | ||
+ | * [[script_custom_listing_format_csv|*]] | ||
+ | * [[script_retry|*]] | ||
+ | * [[script_formatting_timestamp_batch_file|*]] | ||
+ | * [[script_email|*]] | ||
+ | * [[script_vbnet_robust_example|*]] | ||
- | <code batch> | ||
- | winscp.com /command "option batch abort" "option confirm off" "open sftp://user:password@example.com/" "put examplefile.txt /home/user/" "exit" | ||
- | </code> | ||
- | |||
- | However you may want to use a script file anyway, so you can later expand it: | ||
- | |||
- | <code winscp> | ||
- | option batch abort | ||
- | option confirm off | ||
- | open sftp://user:password@example.com/ | ||
- | put examplefile.txt /home/user/ | ||
- | exit | ||
- | </code> | ||
- | |||
- | To run the script use following command (providing you have saved the script to file ''example.txt''): | ||
- | |||
- | <code batch> | ||
- | winscp.com /script=example.txt | ||
- | </code> | ||
- | |||
- | ===== [[upload_multiple_servers]] Upload to multiple servers / Parametrized script ===== | ||
- | If you need to repeat the same task against multiple servers, instead of writing separate and almost identical [[scripting|scripts]] for each server, you can write one parametrized script. | ||
- | |||
- | Following example is parametrized script that accepts one [[scripting#arguments|parameter]] with [[session_url|session URL]] and uploads a fixed local file to a fixed remote directory: | ||
- | |||
- | <code winscp> | ||
- | option batch abort | ||
- | option confirm off | ||
- | open %1% | ||
- | put examplefile.txt /home/user/ | ||
- | exit | ||
- | </code> | ||
- | |||
- | To use the script against multiple servers, just execute the script (saved to file ''script.txt'') repeatedly, using different [[session_url|session URL]] as parameter: | ||
- | |||
- | <code batch> | ||
- | winscp.com /script=script.txt /parameter sftp://martin@server1.example.com/ | ||
- | winscp.com /script=script.txt /parameter sftp://test@server2.example.com/ | ||
- | </code> | ||
- | |||
- | If the script has also other variable parts, like file to upload or remote directory, just replace those parts with additional parameters (''%2%'', ''%3%'', etc). | ||
- | |||
- | //Alternative to using ''/parameter'' switch is [[scripting#variables|using environment variable in the script]].// | ||
- | |||
- | |||
- | ===== [[download_timestamped_filename]] Downloading file to timestamped-filename ===== | ||
- | |||
- | ==== Using WinSCP .NET Assembly ==== | ||
- | Use [[library|WinSCP .NET assembly]] from your favorite language. Use relevant construct of your language or API of your runtime environment for the file name formatting. | ||
- | |||
- | If you do not have your favorite language, use [[library_powershell|PowerShell]]: | ||
- | |||
- | <code powershell> | ||
- | 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) | ||
- | |||
- | $localPath = "c:\downloaded\" | ||
- | $remotePath = "/home/user/" | ||
- | $file = "download.txt" | ||
- | |||
- | # Format timestamp | ||
- | $stamp = $(Get-Date -f "yyyyMMddHHmmss") | ||
- | |||
- | # Download the file and throw on any error | ||
- | $session.GetFiles( | ||
- | ($remotePath + $file), | ||
- | ($localPath + $file + "." + $stamp)).Check() | ||
- | } | ||
- | finally | ||
- | { | ||
- | # Disconnect, clean up | ||
- | $session.Dispose() | ||
- | } | ||
- | |||
- | exit 0 | ||
- | } | ||
- | catch [Exception] | ||
- | { | ||
- | Write-Host $_.Exception.Message | ||
- | exit 1 | ||
- | } | ||
- | </code> | ||
- | |||
- | ==== Using WinSCP Scripting ==== | ||
- | === [[batch]] Using TIMESTAMP Variable === | ||
- | //In the latest beta release//, &beta you can use ''[[scripting#timestamp|%TIMESTAMP%]]'' construct to insert a real-time to a script. | ||
- | |||
- | <code winscp> | ||
- | option batch abort | ||
- | option confirm off | ||
- | open mysession | ||
- | get "/home/user/download.txt" "C:\downloaded\download.txt.%TIMESTAMP#yyyymmddhhnnss%" | ||
- | exit | ||
- | </code> | ||
- | |||
- | |||
- | === [[batch]] From a Batch File === | ||
- | In Windows batch file, you may retrieve current time in locale-independent format using command ''[[http://technet.microsoft.com/en-us/library/bb491034.aspx|wmic]] os get LocalDateTime''. You can parse the value using using [[http://en.wikibooks.org/wiki/Windows_Batch_Scripting#String_processing|string processing syntax]]: | ||
- | |||
- | <code batch> | ||
- | @echo off | ||
- | |||
- | for /F "usebackq tokens=1,2 delims==" %%i in (`wmic os get LocalDateTime /VALUE 2^>NUL`) do if '.%%i.'=='.LocalDateTime.' set LDT=%%j | ||
- | set STAMP=%LDT:~0,4%%LDT:~4,2%%LDT:~6,2%%LDT:~8,2%%LDT:~10,2%%LDT:~12,2% | ||
- | |||
- | winscp.com /script=script.txt | ||
- | </code> | ||
- | |||
- | //Note that the expression after ''set STAMP='' shows how to extract individual date/time components, in case you need to interleave them by some punctuation. If not, you can replace it by simple ''%LDT:~0,14%''.// | ||
- | |||
- | The ''script.txt'' should make use of the variable ''STAMP'' using ''%STAMP%'' [[scripting#variables|syntax]]. For example: | ||
- | |||
- | <code winscp> | ||
- | option batch abort | ||
- | option confirm off | ||
- | open mysession | ||
- | get "/home/user/download.txt" "C:\downloaded\download.txt.%STAMP%" | ||
- | exit | ||
- | </code> | ||
- | |||
- | === From a JScript === | ||
- | You may use following [[guide_automation_advanced#wsh|Windows script host JScript code]] (''example.js''): | ||
- | |||
- | <code javascript> | ||
- | // Local path to download to (keep trailing slash) | ||
- | var LOCALPATH = "c:\\downloaded\\"; | ||
- | // Remote path to download from (keep trailing slash) | ||
- | var REMOTEPATH = "/home/user/"; | ||
- | // File to download | ||
- | var FILE = "download.txt"; | ||
- | // Session to connect to | ||
- | var SESSION = "session"; | ||
- | // 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 it finishes and collect its output | ||
- | var output = exec.StdOut.ReadAll(); | ||
- | // optionally print the output | ||
- | WScript.Echo(output); | ||
- | </code> | ||
- | |||
- | Run the script with command: | ||
- | <code batch> | ||
- | cscript /nologo example.js | ||
- | </code> | ||
- | |||
- | ===== [[download_most_recent_file]] Downloading the most recent file ===== | ||
- | |||
- | ==== [[library]] Using WinSCP .NET Assembly ==== | ||
- | Use [[library|WinSCP .NET assembly]] from your favorite language. | ||
- | |||
- | If you do not have your favorite language, use [[library_powershell|PowerShell]]: | ||
- | |||
- | <code powershell> | ||
- | 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) | ||
- | |||
- | $localPath = "c:\downloaded\" | ||
- | $remotePath = "/home/user/" | ||
- | |||
- | # Gel 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 | ||
- | } | ||
- | </code> | ||
- | |||
- | ==== Using WinSCP Scripting ==== | ||
- | You may use following [[guide_automation_advanced#wsh|Windows script host JScript 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 + "\" /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> | ||
- | cscript /nologo example.js | ||
- | </code> | ||
- | |||
- | ==== 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 ''[[scriptcommand_synchronize|synchronize local]]'' in scripting or ''[[library_session_synchronizedirectories|Session.SynchronizeDirectories(SynchronizationMode.Local, ...)]]'' in .NET assembly); | ||
- | * 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). | ||
- | * 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%" *%%'', or an equivalent in .NET assembly). | ||
- | |||
- | ===== [[upload_most_recent_file]] Uploading the most recent file ===== | ||
- | |||
- | ==== [[library]] Using WinSCP .NET Assembly ==== | ||
- | Use [[library|WinSCP .NET assembly]] from your favorite language. | ||
- | |||
- | If you do not have your favorite language, use [[library_powershell|PowerShell]]: | ||
- | |||
- | <code powershell> | ||
- | 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) | ||
- | |||
- | $localPath = "c:\toupload\" | ||
- | $remotePath = "/home/user/" | ||
- | |||
- | # Gel list of files in the directory | ||
- | $directoryInfo = $session.ListDirectory($remotePath) | ||
- | |||
- | # Select the most recent file. | ||
- | # The !$_.PsIsContainer test excludes subdirectories. | ||
- | # With PowerShell 3.0, you can replace this with -File switch of Get-ChildItem. &win8 | ||
- | $latest = | ||
- | Get-ChildItem -Path $localPath | | ||
- | Where-Object {!$_.PsIsContainer} | | ||
- | Sort-Object LastWriteTime -Descending | | ||
- | Select-Object -First 1 | ||
- | |||
- | # Any file at all? | ||
- | if ($latest -eq $Null) | ||
- | { | ||
- | Write-Host "No file found" | ||
- | exit 1 | ||
- | } | ||
- | |||
- | # Upload the selected file | ||
- | $session.PutFiles($session.EscapeFileMask($localPath + $latest.Name), $remotePath).Check() | ||
- | } | ||
- | finally | ||
- | { | ||
- | # Disconnect, clean up | ||
- | $session.Dispose() | ||
- | } | ||
- | |||
- | exit 0 | ||
- | } | ||
- | catch [Exception] | ||
- | { | ||
- | Write-Host $_.Exception.Message | ||
- | exit 1 | ||
- | } | ||
- | </code> | ||
- | |||
- | ==== Using WinSCP Scripting ==== | ||
- | You may use following batch file that calls WinSCP [[scripting|script]]:((Inspired by SuperUser question [[http://superuser.com/a/158426/213663|Upload only the latest file with WinSCP]].)) | ||
- | |||
- | <code batch> | ||
- | @echo off | ||
- | set SESSION=sftp://user:password@example.com/ | ||
- | set LOCAL_PATH=c:\toupload\ | ||
- | set REMOTE_PATH=/home/user/ | ||
- | |||
- | for /f "delims=" %%i in ('dir /b /od %LOCAL_PATH%\*') do set LATEST=%%i | ||
- | if "%LATEST%" == "" goto NO_FILE | ||
- | |||
- | winscp.com /command ^ | ||
- | "option batch abort" ^ | ||
- | "option confirm off" ^ | ||
- | "open %SESSION%" ^ | ||
- | "put %LOCAL_PATH%%LATEST% %REMOTE_PATH%" ^ | ||
- | "exit" | ||
- | exit %ERRORLEVEL% | ||
- | |||
- | :NO_FILE | ||
- | echo No file found | ||
- | exit 1 | ||
- | </code> | ||
- | |||
- | ==== Alternatives ==== | ||
- | |||
- | Some of following alternatives can be easier to implement or actually even more appropriate for your specific task: | ||
- | |||
- | * Synchronizing a local directory to a remote directory (using ''[[scriptcommand_synchronize|synchronize remote]]'' in scripting or ''[[library_session_synchronizedirectories|Session.SynchronizeDirectories(SynchronizationMode.Remote, ...)]]'' in .NET assembly); | ||
- | * Uploading all files created in the last 24 hours (using [[file_mask|file mask]] ''*>=1D''; e.g. ''%%put -filemask="*>=1D" c:\toupload\*%%'', or an equivalent in .NET assembly). | ||
- | * Uploading all files created today (using ''[[scripting#timestamp|%TIMESTAMP%]]'' syntax to format [[file_mask|file mask]] with today's time constraint, e.g. ''%%put -filemask="*>=%TIMESTAMP#yyyy-mm-dd%" c:\toupload\*%%'', or an equivalent in .NET assembly). | ||
- | |||
- | ===== [[checking_file_existence]] Checking file existence ===== | ||
- | |||
- | |||
- | |||
- | ==== [[remote]] Remote file existence ==== | ||
- | |||
- | === Using WinSCP .NET Assembly === | ||
- | Use method ''[[library_session_fileexists|Session.FileExists]]'' from [[library|WinSCP .NET assembly]]. | ||
- | |||
- | If you do not have your favorite language, use [[library_powershell|PowerShell]]: | ||
- | |||
- | <code powershell> | ||
- | $remotePath = "/home/user/test.txt" | ||
- | |||
- | if ($session.FileExists($remotePath)) | ||
- | { | ||
- | Write-Host ("File {0} exists" -f $remotePath) | ||
- | } | ||
- | </code> | ||
- | |||
- | See complete [[library_session_fileexists#powershell|PowerShell example for Session.FileExists]]. | ||
- | |||
- | If you are not looking for a specific file, but for any file matching a mask (e.g. ''*.txt''), you need to use ''Session.ListDirectory'' and [[library_example_listing_files_matching_wildcard|query returned list of files]]. | ||
- | |||
- | ~~AD~~ | ||
- | |||
- | === [[scripting]] Using WinSCP Scripting === | ||
- | You can use a ''[[scriptcommand_stat|stat]]'' command in ''[[scriptcommand_option|option batch abort]]'' mode to query file attributes. If the file does not exist, the ''stat'' command fails and so does the script. Then, [[scripting#checking_results|test WinSCP exit code]] to determine, if the file exists or not. | ||
- | |||
- | <code batch> | ||
- | @echo off | ||
- | |||
- | set REMOTE_PATH=/home/user/test.txt | ||
- | winscp.com /command "option batch abort" "open mysession" "stat %REMOTE_PATH%" "exit" | ||
- | |||
- | if errorlevel 1 goto error | ||
- | |||
- | echo File %REMOTE_PATH% exists | ||
- | rem Do something | ||
- | exit 0 | ||
- | |||
- | :error | ||
- | echo Error or file %REMOTE_PATH% not exists | ||
- | exit 1 | ||
- | </code> | ||
- | |||
- | ==== [[local]] Local file existence ==== | ||
- | |||
- | * In [[library_powershell|PowerShell]], use ''[[http://technet.microsoft.com/en-us/library/hh849776.aspx|Test-Path]]'' cmdlet. See [[library_session_getfiles#powershell|example]]. | ||
- | * In a batch file, use ''[[http://technet.microsoft.com/en-us/library/cc754335.aspx|if exist]]'' command. See [[guide_automation_conditional#scripting|example]]. | ||
- | * In .NET, use ''[[http://msdn.microsoft.com/en-us/library/system.io.file.exists.aspx|File.Exists]]'' method. See [[library_session_getfiles#csharp|C#]] and [[library_session_getfiles#vbnet|VB.NET]] example. | ||
- | * In WSH, use ''[[http://msdn.microsoft.com/en-us/library/x23stk5t.aspx|Scripting.FileSystemObject.FileExists]]'' method. See [[library_session_getfiles#jscript|JScript]] and [[library_session_getfiles#jscript|VBScript]] example. | ||
- | |||
- | ===== [[local_move_after_successful_upload]] Moving local files to different location after successful upload ===== | ||
- | |||
- | |||
- | |||
- | |||
- | ==== [[library]] Using WinSCP .NET Assembly ==== | ||
- | Use [[library|WinSCP .NET assembly]] from your favorite language. | ||
- | |||
- | If you do not have your favorite language, use [[library_powershell|PowerShell]]: | ||
- | |||
- | <code powershell> | ||
- | 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) | ||
- | |||
- | $localPath = "C:\upload\*" | ||
- | $remotePath = "/home/user/" | ||
- | $backupPath = "C:\backup\" | ||
- | |||
- | # Upload files, collect results | ||
- | $transferResult = $session.PutFiles($localPath, $remotePath) | ||
- | |||
- | # Iterate over every transfer | ||
- | foreach ($transfer in $transferResult.Transfers) | ||
- | { | ||
- | # Success or error? | ||
- | if ($transfer.Error -eq $Null) | ||
- | { | ||
- | Write-Host ("Upload of {0} succeeded, moving to backup" -f | ||
- | $transfer.FileName) | ||
- | # Upload succeeded, move source file to backup | ||
- | Move-Item $transfer.FileName $backupPath | ||
- | } | ||
- | else | ||
- | { | ||
- | Write-Host ("Upload of {0} failed: {1}" -f | ||
- | $transfer.FileName, $transfer.Error.Message) | ||
- | } | ||
- | } | ||
- | } | ||
- | finally | ||
- | { | ||
- | # Disconnect, clean up | ||
- | $session.Dispose() | ||
- | } | ||
- | |||
- | exit 0 | ||
- | } | ||
- | catch [Exception] | ||
- | { | ||
- | Write-Host $_.Exception.Message | ||
- | exit 1 | ||
- | } | ||
- | </code> | ||
- | |||
- | ==== Using WinSCP Scripting ==== | ||
- | WinSCP scripting 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 batch> | ||
- | winscp.com /script=example.txt | ||
- | if errorlevel 1 goto error | ||
- | |||
- | echo Upload succeeded, moving local files | ||
- | move *.* c:\backup\ | ||
- | exit 0 | ||
- | |||
- | :error | ||
- | echo Upload failed, keeping local files | ||
- | exit 1 | ||
- | </code> | ||
- | |||
- | ===== [[synchronize_any_local_file]] Shortcut to synchronize any local directory with remote directory ===== | ||
- | |||
- | |||
- | |||
- | You may want to have a 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:\users\username\www\forum'' with ''/home/user/www/forum''. &winpath | ||
- | |||
- | Such a 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 batch> | ||
- | 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:\Users\username\AppData\Roaming\Microsoft\Windows\SendTo'', you can use //Send To > Your Shortcut// from context menu of any local directory. &winpath | ||
- | |||
- | |||
- | |||
- | ===== [[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 batch> | ||
- | 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 0 | ||
- | |||
- | :error | ||
- | echo Retrieving files failed | ||
- | exit 1 | ||
- | </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 = "/xmllog=" + 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 output IsNot 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]]; | ||
- | * [[library_powershell|Using WinSCP .NET Assembly from PowerShell]]. | ||
- | </trailer> | ||
- | |||
- | <nosplit> | ||
===== Other Examples ===== | ===== Other Examples ===== | ||
* Guide to [[guide_automation|scripting/automation]]; | * Guide to [[guide_automation|scripting/automation]]; | ||
* Guide to [[guide_automation_advanced|advanced scripting]]; | * Guide to [[guide_automation_advanced|advanced scripting]]; | ||
- | * See [[library_examples|WinSCP .NET assembly examples]] for advanced tasks. | + | * See [[library_examples|*]] for advanced tasks. |
- | </nosplit> | + | |