about summary refs log tree commit diff
path: root/Functions/Zftp/zfuget
diff options
context:
space:
mode:
Diffstat (limited to 'Functions/Zftp/zfuget')
-rw-r--r--Functions/Zftp/zfuget147
1 files changed, 147 insertions, 0 deletions
diff --git a/Functions/Zftp/zfuget b/Functions/Zftp/zfuget
new file mode 100644
index 000000000..482da42e9
--- /dev/null
+++ b/Functions/Zftp/zfuget
@@ -0,0 +1,147 @@
+# function zfuget {
+# Get a list of files from the server with update.
+# In other words, only retrieve files which are newer than local
+# ones.  This depends on the clocks being adjusted correctly
+# (i.e. if one is fifteen minutes out, for the next fifteen minutes
+# updates may not be correctly calculated).  However, difficult
+# cases --- where the files are the same size, but the remote is newer,
+# or have different sizes, but the local is newer -- are prompted for.
+#
+# Files are globbed on the remote host --- assuming, of course, they
+# haven't already been globbed local, so use 'noglob' e.g. as
+# `alias zfuget="noglob zfuget"'.
+#
+# Options:
+#  -G    Glob:     turn off globbing
+#  -v    verbose:  print more about the files listed.
+#  -s    silent:   don't ask, just guess.  The guesses are:
+#                - if the files have different sizes but remote is older ) grab
+#                - if they have the same size but remote is newer        )
+#                  which is safe if the remote files are always the right ones.
+#   -t   time:     update the local file times to the same time as the remote.
+#                  Currently this only works if you have the `perl' command,
+#                  and that perl is version 5 with the standard library.
+#                  See the function zfrtime for more gory details.
+
+emulate -L zsh
+
+local loc rem locstats remstats doit tmpfile=${TMPPREFIX}zfuget$$
+local rstat remlist verbose optlist opt bad i silent nglob time
+integer stat do_close
+
+zfuget_print_time() {
+  local tim=$1
+  print -n "$tim[1,4]/$tim[5,6]/$tim[7,8] $tim[9,10]:$tim[11,12].$tim[13,14]"
+  print -n GMT
+}
+
+zfuget_print () {
+  print -n "\nremote $rem ("
+  zfuget_print_time $remstats[2]
+  print -n ", $remstats[1] bytes)\nlocal $loc ("
+  zfuget_print_time $locstats[2]
+  print ", $locstats[1] bytes)"
+}
+
+while [[ $1 = -* ]]; do
+  if [[ $1 = - || $1 = -- ]]; then
+    shift;
+    break;
+  fi
+  optlist=${1#-}
+  for (( i = 1; i <= $#optlist; i++)); do
+    opt=$optlist[$i]
+    case $optlist[$i] in
+      v) verbose=1
+	 ;;
+      s) silent=1
+	 ;;
+      G) nglob=1
+	 ;;
+      t) time=1
+	 ;;
+      *) print option $opt not recognised >&2
+	 ;;
+    esac
+  done
+  shift
+done
+
+[[ -n $bad ]] && return 1
+
+zfautocheck
+
+for remlist in $*; do
+  # zfcd directory hack to put the front back to ~
+  if [[ $remlist == $HOME || $remlist == $HOME/* ]]; then
+    remlist="~${remlist#$HOME}"
+  fi
+  if [[ $nglob != 1 ]]; then
+    zfrglob remlist
+  fi
+  if (( $#remlist )); then
+    for rem in $remlist; do
+      loc=${rem:t}
+      doit=y
+      remstats=()
+      if [[ -f $loc ]]; then
+	zftp local $loc >$tmpfile
+	locstats=($(<$tmpfile))
+	zftp remote $rem >$tmpfile
+	rstat=$?
+	remstats=($(<$tmpfile))
+	rm -f $tmpfile
+	if [[ $rstat = 2 ]]; then
+	  print "Server does not implement full command set required." 1>&2
+	  return 1
+	elif [[ $rstat = 1 ]]; then
+	  print "File not found on server: $rem" 1>&2
+	  stat=1
+	  continue
+	fi
+	[[ $verbose = 1 ]] && zfuget_print
+	if (( $locstats[1] != $remstats[1] )); then
+	  # Files have different sizes
+	  if [[ $locstats[2] > $remstats[2] && $silent != 1 ]]; then
+	    [[ $verbose != 1 ]] && zfuget_print
+	    print "Local file $loc more recent than remote," 1>&2
+	    print -n "but sizes are different.  Transfer anyway [y/n]? " 1>&2
+	    read -q doit
+	  fi
+	else
+	  # Files have same size
+	  if [[ $locstats[2] < $remstats[2] ]]; then
+	    if [[ $silent != 1 ]]; then
+	      [[ $verbose != 1 ]] && zfuget_print
+	      print "Local file $loc has same size as remote," 1>&2
+	      print -n "but local file is older. Transfer anyway [y/n]? " 1>&2
+	      read -q doit
+	    fi
+	  else
+	    # presumably same file, so don't get it.
+	    [[ $verbose = 1 ]] && print Not transferring
+	    doit=n
+	  fi
+	fi
+      else
+	[[ $verbose = 1 ]] && print New file $loc
+      fi
+      if [[ $doit = y ]]; then
+	if zftp get $rem >$loc; then
+	  if [[ $time = 1 ]]; then
+	    # if $remstats is set, it's second element is the remote time
+	    zfrtime $loc $rem $remstats[2]
+	  fi
+	else
+	  stat=$?
+	fi
+	
+      fi
+    done
+  fi
+done
+
+(( do_close )) && zfclose
+
+return $stat
+# }