Home > Articles > Operating Systems, Server > Linux/UNIX/Open Source

  • Print
  • + Share This
From the author of

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 signal—0, or end-of-script—occurs.

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.

  • + Share This
  • 🔖 Save To Your Account