- Working with FTP On the Command Line
- Turning It into a Shell Script
- Where to Go Next
Turning It into a Shell Script
To take a command-line sequence and turn it into a shell script, copy and paste what you typed in and preface it with the following first line to ensure that the shell knows that it is a script:
#!/bin/sh
The result looks like this:
#!/bin/sh ftp laptop.intuitive.com << "EOF" taylor dir quit EOF exit 0
When run, this listing prompts for a password (which is more secure than having a password hard-coded into the script) and displays the remote directory listing.
That's not too useful, though. What we want is to keep a local and remote directory synchronized. To do that, we'll need to use the put command in FTP. And to do that, we'll first want to make sure that we've moved into the proper directory on both the local and remote end.
This turns out to be pretty easy on the remote end because it's just a few lines of modification to the here document being fed to the FTP program:
ftp laptop.intuitive.com << "EOF" taylor cd targetdir put filelist quit EOF
We can't do this exactly, though, because the put instructions will be based on the local directory. One way to do this is to create a compressed archive (a so-called tarball) and upload that, but then the remote files aren't the same without unpacking it. Instead, the key is to create a temporary file that we can build on-the-fly, rather than a here document with predetermined results:
echo "taylor" > $temp echo "cd $targetdir" >> $temp for file in * do if [ -f $file ] ; then echo "put $file $file" >> $temp else echo "skipping $file: not a file." >&2 fi done echo "quit" >> $temp
The for loop here steps through all entries in the current directory; then the if statement uses the -f test to see whether a given entry is a file or not. If it isn't a file, it's skipped.
NOTE
A useful addition to this script would be the capability to recursively traverse subdirectories and the files therein, but that's beyond the scope of this script and would prove fairly tricky to implement in a robust fashion.
The end result is a temporary file that looks like this:
taylor cd somedir put get-files.sh get-files.sh put test.doc test.doc quit
The complete script, including variable initializations, looks like this:
#!/bin/sh temp="/tmp/$(basename $0).$$" ; trap "/bin/rm -f $temp" 0 targetdir="remote-dir" remote="laptop.intuitive.com" echo "taylor" > $temp echo "cd $targetdir" >> $temp for file in * do if [ -f $file ] ; then echo "put $file $file" >> $temp else echo "skipping $file: not a file." >&2 fi done echo "quit" >> $temp ftp $remote < $temp exit 0
As is typical for a well-written shell script, the first section defines all the variables; in this case, our temp file will take on the same name as the script, with the unique process ID (the "$$" expands to that) appended. To keep things clean, the trap function executes the specified command (/bin/rm) when the indicated signal0, or end-of-scriptoccurs.
Let's see what happens when we run this script, shall we?
$ get-dir.sh Connected to 192.168.1.106. 220 local FTP server (lukemftpd 1.1) ready. Name (192.168.1.101:taylor): 331 Password required for taylor. Password: 230 User taylor logged in. Remote system type is UNIX. Using binary mode to transfer files. 250 CWD command successful. local: get-dir.sh remote: get-dir.sh 229 Entering Extended Passive Mode (|||49382|) 150 Opening BINARY mode data connection for 'get-dir.sh'. 100% |*******************************************| 372 248.48 KB/s 00:00 ETA 226 Transfer complete. 372 bytes sent in 00:00 (2.73 KB/s) local: my-spreadsheet.xls remote: my-spreadsheet.xls 229 Entering Extended Passive Mode (|||49383|) 150 Opening BINARY mode data connection for 'my-spreadsheet.xls'. 100% |*******************************************| 82944 1.73 MB/s 00:00 ETA 226 Transfer complete. 82944 bytes sent in 00:00 (472.96 KB/s) local: sample.doc remote: sample.doc 229 Entering Extended Passive Mode (|||49384|) 150 Opening BINARY mode data connection for 'sample.doc'. 100% |*******************************************| 25088 1.19 MB/s 00:00 ETA 226 Transfer complete. 25088 bytes sent in 00:00 (131.40 KB/s) 221 Thank you for using the FTP service $
All we had to do was type in the name of the script (get-dir.sh) and the password when prompted, and automatically three files were transferred from the local directory to target-dir on the remote system: get-dir.sh, my-spreadsheet.xls, and sample.doc. Short and sweet.