📄 frcp
字号:
#! /bin/bash## original from:## @(#) frcp.ksh 2.2 93/11/14# 92/06/29 john h. dubois iii (john@armory.com)# 92/10/14 Cleaned up, improved, added -d and -r options# 92/11/11 Made work with a dest of '.'# 93/07/09 Added -l and -n options, & login as anonymous if no .netrc entry# 93/11/14 Use either passwd or password in .netrc, since ftp does.## conversion to bash v2 syntax by Chet Ramey## frcp: ftp front end with rcp-like syntax.# Note: requires any machine names given to be listed with# user and password in .netrc. If not, anonymous FTP is# done.## full path to ftp binaryif [ -x /usr/bin/ftp ]; then FTP=/usr/bin/ftp;elif [ -x /usr/ucb/ftp ]; then FTP=/usr/ucb/ftpelse FTP=ftpfiistrue(){ test 0 -ne "$1"}isfalse(){ test 0 -eq "$1"}# For each filename given, put the filename in filename[n]# and the machine it is on in machine[n].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}# CopyFiles: issue ftp(TC) commands to copy files.# Usage: CopyFiles [sourcemachine:]sourcepath ... [destmachine:]destpath# Global vars:# Uses LocalMach (should be name of local machine)# Sets global arrs machine[]/filename[]function CopyFiles { unset machine[*] filename[*] SplitNames "$@" # split names into filename[1..n] and machine[1..n] local DestMach=${machine[$#]} # Machine to copy files to local DestPath=${filename[$#]} # Destination file/dir unset machine[$#] filename[$#] [ -z "$DestPath" ] && DestPath=. # dest was given as machine: # Try to determine if destination should be a directory # so that it can be forced to be a directory. case "$DestPath" in */) ;; # don't add / if trailing / already present *) if [ $# -gt 2 ] || # if more than two args given, last must be a dir # If dest in on local machine, check whether it is a directory [ $DestMach = $LocalMach -a -d $DestPath ] || # If dest ends with . or .., it is a directory lastisdot "$DestPath" then DestPath=$DestPath/ fi ;; esac # If one of the above tests made us think dest is a directory, # but it isn't, complain case "$DestPath" in */) if [ "$DestMach" = "$LocalMach" ] && [ ! -d "$DestPath" ]; then echo "Destination is not a directory." 1>&2 exit 1 fi ;; esac DoCopy "$DestMach" "$DestPath"}# Usage: OpenMachine machine-name# Emits login sequence or doesn't, depending on .netrc file and global# variables anon and noanonOpenMachine (){ 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}# Usage: DoCopy destination-machine destination-path# Copies the files in global arrs machine[]/filename[] to the given dest# Global vars:# Uses machine[], filename[], LocalMach, checkDoCopy (){ local DestMach=$1 local DestPath=$2 local OpenMach # Machine that connection is currently open to local OWD=$PWD SourceMach SourceFile local FileName typeset -i i=1 while [ $i -le ${#machine[*]} ]; do istrue $check && verboseprint "runique" SourceMach=${machine[i]} SourceFile=${filename[i]} DestFile=$DestPath # if DestPath is a dir, # add source filename to it without source path 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 destination is on local machine, # the dest will be a full dir/filename if istrue $createdirs; then MakeDir "${DestFile%/*}" || continue fi if [ $SourceMach != "$OpenMach" ]; then OpenMachine $SourceMach OpenMach=$SourceMach fi # If source filename has wildcards ([, ], *, ?) do an mget 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}# Start of main programname=${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:filenameIf remote filenames contain wildcards, they will be globbed on the remotemachine. Make sure they are quoted when $name is invoked.If the invoking user's .netrc file (see ftp(TC)) contains an entry for theremote system with a login and password supplied, $name will log in usingthe given login and password. If not, $name will login in as useranonymous 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 0fitypeset -i check=0 createdirs=0 readinput=0 anon=0 noanon=0while getopts :cdflnr Optiondo 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;; esacdoneshift $((OPTIND-1))LocalMach=`hostname` if istrue $readinput; then while read line; do CopyFiles $line done | $FTP -nvelse if [ $# -lt 2 ]; then echo "$name: Not enough arguments. Use -h for help." 1>&2 exit fi CopyFiles "$@" | $FTP -nvfi
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -