Running WinSCP with REBOL
I just found WinSCP last week and I love it. It solved a big problem for me involving sending files securely and automatically. The method I chose to control the operation is a scripting language called REBOL. It is not a popular language, so I thought that in the interest of spreading knowledge, I would post the program I wrote so locate all folders in a specified folder, send each folder to a secure ftp site, and delete the folder after sending it. It shows the technique of generating a command line to run WinSCP. The script below is a bit long, but it is written in a plodding manner that should make it easy to understand. Thank you. I apologize if this comes through as a mess.
REBOL [ Title: "Securely send folders by sftp" Purpose: {Get the names of all the folders in a special transfer area. Send them to a secure server and remove them.} ] ;; [---------------------------------------------------------------------------] ;; [ The purpose of this program is to identify all the files in the ] ;; [ source folder, transmit them to a destination, and then delete them. ] ;; [ We will send them with a secure ftp program that can be scripted. ] ;; [ It appears that REBOL can't do sftp. ] ;; [ The scriptable sftp program we use is at: https://winscp.net ] ;; [ ] ;; [ The program uses the REBOL "call" function to call WinSCP (the sriptable ] ;; [ sftp client) to send the files, and Powershell to remove the files. ] ;; [ The reason it uses WinSCP is that REBOL can't do secure ftp, and the ] ;; [ reason it uses Powershell to delete files is that it seems REBOL can't ] ;; [ delete a folder without first deleting everything in it, and ] ;; [ Powershell can simply with the "recurse" option. ] ;; [ It appears that the "call/wait" function does indeed wait until the ] ;; [ called program is done, so there is no danger of trying to remove a ] ;; [ folder before it has been sent. ] ;; [ ] ;; [ In the original use scenario for this program, the data to be sent ] ;; [ was in folders, and each folder was to be sent, recursively. ] ;; [ WinSCP handles this very nicely. The same syntax works for individual ] ;; [ files, so while this program originally was used to send folders, ] ;; [ it would work as-is (or maybe with some minor change) for individual ] ;; [ files. ] ;; [---------------------------------------------------------------------------] ;; [---------------------------------------------------------------------------] ;; [ Change the following items for your own installation. ] ;; [---------------------------------------------------------------------------] SOURCE-DIR: %/C/OUTBOX/ ;; Folder of folders to be sent SFTP-SERVER: "sft.servername.com" ;; Destination server USERID: "UserID" ;; Account on above server PASSWORD: "Password" ;; Password for above account LOG-FILE-ID: %SendFolders.log ;; Log what we do for auditing LOG-FOLDER: %/SERVERNAME/TaskLogs/ ;; Send log here ;; [---------------------------------------------------------------------------] ;; [ HOME-DIR Our starting folder because we will have to move. ] ;; [ SENT-ITEM-LOCAL: The local-fomat name of the item we are going to send. ] ;; [ BAT-FILE: A generated DOS batch file to run WinSCP. ] ;; [ PS1-FILE: A generated Powershell script to remove folders. ] ;; [ FILE-LIST: A list of all the items we are about to send. ] ;; [---------------------------------------------------------------------------] HOME-DIR: what-dir SENT-ITEM-LOCAL: none BAT-FILE: "" PS1-FILE: "" FILE-LIST: [] ;; [---------------------------------------------------------------------------] ;; [ Using a file/folder name from the list, generate its full name in ] ;; [ a format suitable for the computer on which this program is running, ] ;; [ which has to be a Windows computer since WinSCP runs on Windows. ] ;; [---------------------------------------------------------------------------] GENERATE-FILE-NAMES: func [ SINGLE-FILE-ID ] [ SENT-ITEM-LOCAL: to-local-file rejoin [ to-string SOURCE-DIR to-string SINGLE-FILE-ID ] ] ;; [---------------------------------------------------------------------------] ;; [ After the local file name is generated, generate the batch file ] ;; [ command that will run WinSCP. ] ;; [---------------------------------------------------------------------------] GENERATE-BATCH-FILE: does [ BAT-FILE: copy "" BAT-FILE: rejoin [ {winscp.com /command } {"open } USERID {:} PASSWORD {@} SFTP-SERVER {" } {"put } SENT-ITEM-LOCAL {" } {"close" } {"exit"} ] ] ;; [---------------------------------------------------------------------------] ;; [ After the local file name is generated, generate a Powershell command ] ;; [ to remove the folder after it has been sent. ] ;; [---------------------------------------------------------------------------] GENERATE-REMOVE-FILE: does [ PS1-FILE: copy "" PS1-FILE: rejoin [ {powershell -command } {"Remove-Item } SENT-ITEM-LOCAL { -recurse" } ] ] ;; [---------------------------------------------------------------------------] ;; [ Log a line of text with a date stamp. ] ;; [---------------------------------------------------------------------------] LOG-EVENT: func [ LOG-LINE ] [ write/append to-file rejoin [HOME-DIR LOG-FILE-ID] rejoin [ now " " LOG-LINE newline ] ] ;; [---------------------------------------------------------------------------] ;; [ Go to the folder where we expect to find the folders to send. ] ;; [ Get a list of all folder names currently in the source directory. ] ;; [---------------------------------------------------------------------------] LOG-EVENT "BOJ SendCaseFiles" change-dir SOURCE-DIR FILE-LIST: read %. if equal? 0 length? FILE-LIST [ LOG-EVENT "No items found to send." ] ;; [---------------------------------------------------------------------------] ;; [ For each item on the list, ] ;; [ 1. Generate the full name of the item in Windows format. ] ;; [ 2. Generate the DOS command to send the item. ] ;; [ 3. Generate the Powershell command to delete the item. ] ;; [ 4. Send the item using the generated command. ] ;; [ 5. Delete the item using the generated command. ] ;; [ Log the steps as we do them. ] ;; [---------------------------------------------------------------------------] foreach FILE-ID FILE-LIST [ GENERATE-FILE-NAMES FILE-ID GENERATE-BATCH-FILE GENERATE-REMOVE-FILE LOG-EVENT replace copy BAT-FILE PASSWORD "???????" call/wait BAT-FILE LOG-EVENT rejoin [FILE-ID " sent."] LOG-EVENT PS1-FILE call/wait PS1-FILE LOG-EVENT rejoin [FILE-ID " removed."] ] ;; [---------------------------------------------------------------------------] ;; [ Finish the log for this run, and then send the log to a different ] ;; [ area for viewing. (Originally, this program was run on a secure server.) ] ;; [---------------------------------------------------------------------------] LOG-EVENT "EOJ SendCaseFiles" write to-file rejoin [LOG-FOLDER LOG-FILE-ID] read to-file rejoin [HOME-DIR LOG-FILE-ID] ;;Uncomment the "halt" for debugging. ;halt