#! /bin/bash
if [ -x /usr/bin/ftp ]; then
FTP=/usr/bin/ftp;
elif [ -x /usr/ucb/ftp ]; then
FTP=/usr/ucb/ftp
else
FTP=ftp
fi
istrue()
{
test 0 -ne "$1"
}
isfalse()
{
test 0 -eq "$1"
}
function SplitNames {
typeset file
typeset -i i=1
unset filename[*] machine[*]
for file; do
case "$file" in
*:*) machine[i]=${file%%:*} ;;
*) machine[i]=$LocalMach ;;
esac
filename[i]=${file let i+=1
done
}
function verboseprint {
echo "$@"
echo "$@" 1>&2
}
function MakeDir {
OFS=$IFS
local IFS=/ dir component
case "$1" in
/*) ;;
*) dir=.
esac
set -- $1
IFS=$OFS
for component; do
dir=$dir/$component
if [ ! -d "$dir" ]; then
if mkdir "$dir"; then :; else
echo "Could not make directory $dir." >&2
return 1
fi
fi
done
return 0
}
lastisdot ()
{
case "$1" in
*/.|*/..) return 0;;
*) return 1;;
esac
}
function CopyFiles {
unset machine[*] filename[*]
SplitNames "$@"
local DestMach=${machine[$ local DestPath=${filename[$
unset machine[$
[ -z "$DestPath" ] && DestPath=.
case "$DestPath" in
*/) ;; *) if [ $ [ $DestMach = $LocalMach ] && [ -d "$DestPath" ] ||
lastisdot "$DestPath"
then
DestPath=$DestPath/
fi ;;
esac
case "$DestPath" in
*/) if [ "$DestMach" = "$LocalMach" ] && [ ! -d "$DestPath" ]; then
echo "Destination is not a directory." 1>&2
exit 1
fi ;;
esac
DoCopy "$DestMach" "$DestPath"
}
OpenMachine ()
{
local machine=$1 netrc=$HOME/.netrc user= password=
if isfalse $anon && [ -r $netrc ]; then
set -- $(gawk '
/machine (.* )?'"$machine"'($| )/,/^ *$/ {
Fields[$1] = $2
if ("passwd" in Fields)
Fields["password"] = Fields["passwd"]
if ("login" in Fields && "password" in Fields) {
print Fields["login"] " " Fields["password"]
exit
}
}
' $netrc )
user=$1
password=$2
fi
if [ -z "$password" ]; then
if istrue $noanon; then
echo "No .netrc entry for machine $machine" 1>&2
exit 1
fi
user=anonymous
password=$USER@$LocalMach
fi
verboseprint open $machine
echo user $user "*******" 1>&2
echo user $user $password
}
DoCopy ()
{
local DestMach=$1
local DestPath=$2
local OpenMach local OWD=$PWD SourceMach SourceFile
local FileName
typeset -i i=1
while [ $i -le ${ istrue $check && verboseprint "runique"
SourceMach=${machine[i]}
SourceFile=${filename[i]}
DestFile=$DestPath
case "$DestFile" in
*/) DestFile=$DestFile${SourceFile esac
if [ $SourceMach = $LocalMach ]; then
if [ $DestMach != "$OpenMach" ]; then
OpenMachine $DestMach
OpenMach=$DestMach
fi
verboseprint put $SourceFile $DestFile
elif [ $DestMach = $LocalMach ]; then
if istrue $check && [ -f "$DestFile" ]; then
echo "$DestFile already exists." 1>&2
continue
fi
if istrue $createdirs; then
MakeDir "${DestFile%/*}" || continue
fi
if [ $SourceMach != "$OpenMach" ]; then
OpenMachine $SourceMach
OpenMach=$SourceMach
fi
case "$SourceFile" in
\[*\]|*\**|*\?*)
verboseprint lcd "$DestFile"
verboseprint mget "$SourceFile"
verboseprint lcd $OWD ;;
*) verboseprint get "$SourceFile" "$DestFile" ;;
esac
else
echo "Neither source machine \"$SourceMach\" "\
"nor destination machine \"$DestMach\" is local." 1>&2
fi
let i+=1
done
}
name=${0
if [ "$1" = -h ]; then
echo \
"$name: do ftp transfers using rcp-style parameters.
Usage: $name <source> <destpath> or $name <source> [<source> ...] <destdir>
At least one of <source> and <destpath> must be the local system.
A remote filename is given as machinename:filename
If remote filenames contain wildcards, they will be globbed on the remote
machine. Make sure they are quoted when $name is invoked.
If the invoking user's .netrc file (see ftp(TC)) contains an entry for the
remote system with a login and password supplied, $name will log in using
the given login and password. If not, $name will login in as user
anonymous and with the user@localsystem as the password.
Options:
-c: check: do not overwrite files.
-d: create directories as needed.
-f: force: overwrite files (default).
-h: print this help.
-l: fail if there is no entry with login and password for the remote system,
instead of logging in as anonymous.
-n: log in as anonymous even if there is an entry for the remote system in
the user's .netrc file.
-r: read source/dest filename pairs from the standard input,
one pair per line, and copy files accordingly."
exit 0
fi
typeset -i check=0 createdirs=0 readinput=0 anon=0 noanon=0
while getopts :cdflnr Option
do
case "$Option" in
c) check=1;;
d) createdirs=1;;
f) check=0;;
l) noanon=1;;
n) anon=1;;
r) readinput=1;;
\?) echo "$OPTARG: invalid option."; exit 1;;
esac
done
shift $((OPTIND-1))
LocalMach=`hostname`
if istrue $readinput; then
while read line; do
CopyFiles $line
done | $FTP -nv
else
if [ $ echo "$name: Not enough arguments. Use -h for help." 1>&2
exit
fi
CopyFiles "$@" | $FTP -nv
fi