FTP上传整个目录

目录

AIX的FTP没有上传整个目录的命令,每次传数据前都要修改要创建的目录列表很费劲,就粗略写了个上传整个目录的shell脚本。

目前,我写了两版。刚接触shell变成,还没有考虑各种异常情况,也没经过详尽的测试,没在业务中使用,后面会在使用过程中逐渐完善。
第一版比较繁琐。参照网上某博文的方法,通过find命令找目录和文件。每个目录都在服务器端创建下,在通过find得到本地文件绝对路径上传到相应的服务器绝对路径。想加入判断是否覆盖的交互功能,没有成功。代码如下:
[shell collapse=”true”]
#!/bin/ksh –
# upload all files in some directory by FTP
# Usage:
# upload_dir.sh
# [-f|–ftp ftp_address] # ftp address
# [-u|–username ftp_user] # ftp username
# [-p|–passwd ftp_passwd] # ftp password
# [-t|–type ftp_trans_type] # ascii|binary
# [-a] [-b] # a: ascii; b: binary
# [-i|I] # i: ignore prompt
# source_dir target_dir

# 2013.04.16
set -x
error()
{
echo “$@” 1>&2
usage_and_exit 1
}
usage()
{
cat «eof Usage: upload_dir.sh [-f|–ftp ftp_address] [-u|–username ftp_user] [-p|–passwd ftp_passwd] [-t|–type ftp_trans_type] [-a] [-b] [-i|I] source_dir target_dir EOF } usage_and_exit() { usage exit $1 } warning() { echo “$@” 1>&2
exitcode=`expr $exitcode + 1`
}
PROGRAM=`basename $0`
exitcode=0
ftp_address=
ftp_user=
ftp_passwd=
ftp_trans_type=assic
ftp_ignore_prompt=-i
source_dir=
target_dir=
while test $# -gt 0
do
case $1 in
-h | –help)
usage_and_exit
;;
-u | –username | –user)
shift
ftp_user=$1
;;
-p | –passwd)
shift
ftp_passwd=$1
;;
-f | –ftp)
shift
ftp_address=$1
;;
-a | –ascii)
ftp_trans_type=assic
;;
-b | –binary)
ftp_trans_type=binary
;;
-t | –type)
shift
ftp_trans_type=$1
;;
-i | –ignore)
ftp_ignore_prompt=-i
;;
-I | –noignroe)
ftp_ignore_prompt=
;;
-)
error “Unrecgnized option: $1”
;;
)
break
;;
esac
shift
done
if [ $# -eq 2 ]
then
source_dir=$1
if ! [ -d $source_dir ]
then
error “Unrecgnized diretory: $source_dir”
fi
target_dir=$2
else
usage_and_exit
fi
if [ ! “$ftp_address” ]
then
printf “ftp address:”
read ftp_address
fi
if [ ! “$ftp_user” ]
then
printf “user name:”
read ftp_user
fi
if [ ! “$ftp_passwd” ]
then
printf “password:”
read -s ftp_passwd
fi
cat > ftp_commands.txt «eof user $ftp_user $ftp_passwd $ftp_trans_type EOF update_dir=$( find $source_dir -type d | sed -e “s;$source_dir;$target_dir;” | awk ‘{print “mkdir " $0 }’ ) update_file=$( find $source_dir -type f | awk -v source_dir=$source_dir -v target_dir=$target_dir ‘{ sfile=$0 tfile=sub(source_dir,target_dir,sfile) print “put " $0 " " sfile }’ ) printf “$update_dir\n” | while read line do echo $line »ftp_commands.txt
done
counts=0
printf “$update_file\n” |
while read line
do
echo $line»ftp_commands.txt
done
ftp $ftp_ignore_promp -nv $ftp_address < ./ftp_commands.txt set +x test $exitcode -gt 125 && exitcode=125 exit $exitcode [/shell] 第二版在同事的指点下,用
代替目录下面所有文件,并用mput上传,这样只需用一次find找出所有目录即可,代码更简洁。 [shell collapse=“true”] #!/bin/ksh - # upload all files in some directory by FTP # Usage: # upload_dir.sh # [-f|–ftp ftp_address] # ftp address # [-u|–username ftp_user] # ftp username # [-p|–passwd ftp_passwd] # ftp password # [-t|–type ftp_trans_type] # ascii|binary # [-a] [-b] # a: ascii; b: binary # source_dir target_dir # # v1 2013.04.16 # v2 2013.04.25 set -x error() { echo “$@” 1>&2
usage_and_exit 1
}
usage()
{
cat «eof Usage: upload_dir.sh [-f|–ftp ftp_address] [-u|–username ftp_user] [-p|–passwd ftp_passwd] [-t|–type ftp_trans_type] [-a] [-b] source_dir target_dir EOF } usage_and_exit() { usage exit $1 } warning() { echo “$@” 1>&2
exitcode=`expr $exitcode + 1`
}
PROGRAM=`basename $0`
exitcode=0
ftp_address=
ftp_user=
ftp_passwd=
ftp_trans_type=assic
#ftp_ignore_prompt=-i
ftp_command_file=ftp_commands.log
source_dir=
target_dir=
while test $# -gt 0
do
case $1 in
-h | –help)
usage_and_exit
;;
-u | –username | –user)
shift
ftp_user=$1
;;
-p | –passwd)
shift
ftp_passwd=$1
;;
-f | –ftp)
shift
ftp_address=$1
;;
-a | –ascii)
ftp_trans_type=ascii
;;
-b | –binary)
ftp_trans_type=binary
;;
-t | –type)
shift
ftp_trans_type=$1
;;
# -i | –ignore)
# ftp_ignore_prompt=-i
# ;;
# -I | –noignroe)
# ftp_ignore_prompt=
# ;;
-
)
error “Unrecgnized option: $1”
;;
*)
break
;;
esac
shift
done
if [ $# -eq 2 ]
then
source_dir=$1
if ! [ -d $source_dir ]
then
error “Unrecgnized diretory: $source_dir”
fi
target_dir=$2
else
usage_and_exit
fi
if [ ! “$ftp_address” ]
then
printf “ftp address:”
read ftp_address
fi
if [ ! “$ftp_user” ]
then
printf “user name:”
read ftp_user
fi
if [ ! “$ftp_passwd” ]
then
printf “password:”
read -s ftp_passwd
fi
cat > $ftp_command_file «eof user $ftp_user $ftp_passwd $ftp_trans_type EOF #if [ “X$ftp_ignore_prompt” = “X-i” ] #then # echo “prompt” »$ftp_command_file
#fi
find $source_dir -type d |
sed -e “s;$source_dir;$target_dir;” |
awk ‘{print “mkdir ” $0 }’ »$ftp_command_file
find $source_dir -type d |
awk -v source_dir=$source_dir -v target_dir=$target_dir ‘{
remote_dir=$0
sub(source_dir,target_dir,remote_dir)
print “cd ” remote_dir
print “lcd ” $0
print “mput \*\n”
}’ »$ftp_command_file
echo “bye” »$ftp_command_file
ftp -niv $ftp_address < $ftp_command_file set +x test $exitcode -gt 125 && exitcode=125 exit $exitcode [/shell] 第二版也不好,应该还有更高效、简洁的算法,得上网搜一搜。 第三版去掉没实现的交互功能,本地目录可以用相对路径,但远端依然得用绝对路径,并可以上传多个本地目录。 [shell] #/bin/ksh - # upload all files in some directory by FTP # Usage: # upload_dir.sh # [-f|–ftp ftp_address] # ftp address # [-u|–username ftp_user] # ftp username # [-p|–passwd ftp_passwd] # ftp password # [-t|–type ftp_trans_type] # a|asc|ascii ascii # # b|bin|binary binary # source_dir1 [source_dir2 source_dir3 …] target_dir # # v1 2013.04.16 # v2 2013.04.25 # v2.1 2013.04.26 # v3 2013.05.02 set -x error() { echo “$@” 1>&2
usage_and_exit 1
}
usage()
{
cat «eof Usage: upload_dir.sh [-f|–ftp ftp_address] [-u|–username ftp_user] [-p|–passwd ftp_passwd] [-t|–type ftp_trans_type] # a|asc|ascii ascii # b|bin|binary binary source_dir [source_dir2 source_dir3 …] target_dir EOF } usage_and_exit() { usage exit $1 } warning() { echo “$@” 1>&2
exitcode=`expr $exitcode + 1`
}
PROGRAM=`basename $0`
exitcode=0
ftp_address=
ftp_user=
ftp_passwd=
ftp_trans_type=assic
ftp_command_file=ftp_commands.log
source_dir_pre=
source_dir=
target_dir=
while test $# -gt 0
do
case $1 in
-h | –help)
usage_and_exit
;;
-u | –username | –user)
shift
ftp_user=$1
;;
-p | –passwd)
shift
ftp_passwd=$1
;;
-f | –ftp)
shift
ftp_address=$1
;;
-t | –type)
shift
case $1 in
a | asc | asic |ascii)
ftp_trans_type=ascii
;;
b | bin | binary)
ftp_trans_type=binary
;;
)
error “Unrecgnized type: $1”
;;
esac
;;
-
)
error “Unrecgnized option: $1”
;;
*)
break
;;
esac
shift
done
# TODO: multi source directories
if [ $# -lt 2 ]
then
usage_and_exit
fi
count=0
while [ $# -ge 2 ]
do
# source directory
source_dir[$count]=$1
if ! [ -d ${source_dir[$count]} ]
then
error “Unrecgnized diretory: ${source_dir[$count]}”
else

if echo ${source_dir[$count]} | grep -qv “^/”
then
source_dir[$count]=$( cd ${source_dir[$count]};pwd )
fi
fi
# target_directory
source_dir_pre=`dirname $source_dir`
shift
count=$(($count+1));
done
target_dir=$1
if [ ! “$ftp_address” ]
then
printf “ftp address:”
read ftp_address
fi
if [ ! “$ftp_user” ]
then
printf “user name:”
read ftp_user
fi
if [ ! “$ftp_passwd” ]
then
printf “password:”
read -s ftp_passwd
fi
cat > $ftp_command_file «eof user $ftp_user $ftp_passwd $ftp_trans_type EOF # make all directories for dir_item in ${source_dir[]} do source_dir_pre=`dirname $dir_item` find $dir_item -type d | sed -e “s;$source_dir_pre;$target_dir;” | awk ‘{print “mkdir " $0 }’ »$ftp_command_file
done
# put all files
for dir_item in ${source_dir[
]}
do
source_dir_pre=`dirname $dir_item`
find $dir_item -type d |
awk -v source_dir_pre=$source_dir_pre -v target_dir=$target_dir ‘{
remote_dir=$0
sub(source_dir_pre,target_dir,remote_dir)
print “cd ” remote_dir
print “lcd ” $0
print “mput \*\n”
}’ »$ftp_command_file
done
echo “bye” »$ftp_command_file
ftp -niv $ftp_address < $ftp_command_file set +x test $exitcode -gt 125 && exitcode=125 exit $exitcode [/shell]