Automating FTP with a Non-Interactive FTP Client

Sometimes FTP has to be used to transfer files instead of one of the more secure alternatives, like SCP. Since the FTP client ftp only supports interactive mode, it can be hard to automate when being called from a script.

The script below is used — almost — the same way as a the scp command is. Its first arguments are files to be copied, and the final argument is the FTP address to send them to, similar to the URI used with scp.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#!/bin/bash
if [ $# -lt 2 ]; then
echo Usage: $(basename $0) SOURCE... USERNAME:PASSWORD@HOST:DEST_DIR
exit 1
fi
from=${@: 1:$(($#-1))}
dest=${@: -1:1}
read user password host path <<< $(echo $dest | sed -n 's/^\([^:]*\)\(:\(.*\)\)\?@\([^:]*\)\(:\(.*\)\)\?$/\1 \3 \4 \6/p')
[ "$path" == "" ] && path=.
[ "$user" == "" ] && user=anonymous && password=none
put_commands=""
for f in $from; do
[ ! -f $f ] && echo File does not exist: $f && exit 1
put_commands=$put_commands$'\nput '$f' '$(basename $f)
done
ftp -inv <<EOF
open $host
user $user $password
binary
cd $path
$put_commands
bye
<<EOF