mirror of
git://git.code.sf.net/p/zsh/code
synced 2025-01-01 05:16:05 +01:00
Initial revision
This commit is contained in:
parent
e74702b467
commit
e8eb43fc30
29 changed files with 1798 additions and 0 deletions
435
Doc/Zsh/zftpsys.yo
Normal file
435
Doc/Zsh/zftpsys.yo
Normal file
|
@ -0,0 +1,435 @@
|
|||
texinode(Zftp Function System)()(Completion System)(Top)
|
||||
chapter(Zftp Function System)
|
||||
cindex(zftp, function system)
|
||||
sect(Description)
|
||||
|
||||
This describes the set of shell functions supplied with the source
|
||||
distribution as an interface to the tt(zftp) builtin command, allowing you
|
||||
to perform FTP operations from the shell command line or within functions
|
||||
or scripts. The interface is similar to a traditional FTP client (e.g. the
|
||||
manref(ftp)(1) command itself), but as it is entirely done within the shell
|
||||
all the familar completion, editing and globbing features, and so on, are
|
||||
present, and macros are particularly simple to write as they are just
|
||||
ordinary shell functions.
|
||||
|
||||
The prerequisite is that the tt(zftp) command, as described in
|
||||
ifzman(\
|
||||
zmanref(zshmodules)
|
||||
)\
|
||||
ifnzman(\
|
||||
noderef(The zftp Module)
|
||||
), must be available in the
|
||||
version of tt(zsh) installed at your site. If the shell is configured to
|
||||
load new commands at run time, it probably is: typing tt(zmodload zftp)
|
||||
will make sure (if that runs silently, it has worked). If this is not the
|
||||
case, it is possible tt(zftp) was linked into the shell anyway: to test
|
||||
this, type tt(which zftp) and if tt(zftp) is available you will get the
|
||||
message tt(zftp: shell built-in command).
|
||||
|
||||
Commands given directly with tt(zftp) builtin may be interspersed between
|
||||
the functions in this suite; in a few cases, using tt(zftp) directly may
|
||||
cause some of the status information stored in shell parameters to become
|
||||
invalid. Note in particular the description of the variables
|
||||
tt($ZFTP_TMOUT), tt($ZFTP_PREFS) and tt($ZFTP_VERBOSE) for tt(zftp).
|
||||
|
||||
startmenu()
|
||||
menu(Installation)
|
||||
menu(Zftp Functions)
|
||||
menu(Miscellaneous Features)
|
||||
endmenu()
|
||||
|
||||
texinode(Installation)(Zftp Functions)()(Zftp Function System)
|
||||
sect(Installation)
|
||||
|
||||
You should make sure all the functions from the tt(Functions/Zftp)
|
||||
directory of the source distribution are available; they all begin with the
|
||||
two letters tt(zf). They may already have been installed on your system;
|
||||
otherwise, you will need to find them and copy them. The directory should
|
||||
appear as one of the elements of the tt($fpath) array, and the functions
|
||||
should be autoloaded. Finally, to initialise the use of the system you
|
||||
need to call the tt(zfinit) function. The following code in your
|
||||
tt(.zshrc) will arrange for this; assume the functions are stored in the
|
||||
directory tt(~/myfns):
|
||||
|
||||
tt(indent(
|
||||
nofill(fpath=(~/myfns $fpath))
|
||||
nofill(autoload ~/myfns/zf*(:t))
|
||||
nofill(zfinit)
|
||||
))
|
||||
|
||||
Note that tt(zfinit) assumes you are using the tt(zmodload) method to
|
||||
load the tt(zftp) command. If it is already built into the shell, change
|
||||
tt(zfinit) to tt(zfinit -n).
|
||||
|
||||
texinode(Zftp Functions)(Miscellaneous Features)(Installation)(Zftp Function System)
|
||||
sect(Functions)
|
||||
|
||||
The sequence of operations in performing a file transfer is essentially the
|
||||
same as that in a standard FTP client.
|
||||
|
||||
subsect(Opening a connection)
|
||||
startitem()
|
||||
item(tt(zfparams [ var(host) [ var(user) [ var(password) ... ] ] ]))(
|
||||
Set or show the parameters for a future tt(zfopen) with no arguments. If
|
||||
no arguments are given, the current parameters are displayed (the password
|
||||
will be shown as a line of asterisks). If a host is given, and either the
|
||||
var(user) or var(password) is not, they will be prompted for; also, any
|
||||
parameter given as `tt(?)' will be prompted for.
|
||||
|
||||
As tt(zfopen) calls tt(zfparams) to store the parameters, this usually need
|
||||
not be called directly.
|
||||
)
|
||||
item(tt(zfopen [ -1 ] [ var(host) [ var(user) [ var(password) [ var(account) ] ] ] ]))(
|
||||
If var(host) is present, open a connection to that host under username
|
||||
var(user) with password var(password) (and, on the rare occasions when it
|
||||
is necessary account var(account)). If a necessary parameter is missing or
|
||||
given as `tt(?)' it will be prompted for. If var(host) is not present, use
|
||||
a previously stored set of parameters.
|
||||
|
||||
If the command was successful, and the terminal is an tt(xterm), a summary
|
||||
will appear in the title bar, giving the local tt(host:directory) and the
|
||||
remote tt(host:directory); this is handled by the function tt(zftp_chpwd),
|
||||
described below.
|
||||
|
||||
Normally, the var(host), var(user) and var(password) are internally
|
||||
recorded for later re-opening, either by a tt(zfopen) with no arguments, or
|
||||
automatically (see below). With the option tt(-1), no information is
|
||||
stored.
|
||||
)
|
||||
item(tt(zfanon [ -1 ] var(host)))(
|
||||
Open a connection var(host) for anonymous FTP. The username used is
|
||||
tt(anonymous). The password (which will be reported the first time) is
|
||||
generated from var(user)tt(@)tt(host); this is then stored in the shell
|
||||
parameter tt($EMAIL_ADDR) which can alternatively be set manually to a
|
||||
suitable string.
|
||||
)
|
||||
enditem()
|
||||
|
||||
subsect(Directory management)
|
||||
startitem()
|
||||
xitem(tt(zfcd [ var(dir) ]))
|
||||
xitem(tt(zfcd -))
|
||||
item(tt(zfcd var(old) var(new)))(
|
||||
Change the current directory on the remote server: this is implemented to
|
||||
have many of the features of the shell builtin tt(cd).
|
||||
|
||||
In the first form with var(dir) present, change to the directory var(dir).
|
||||
The command tt(zfcd ..) is treated specially, so is guaranteed to work on
|
||||
non-UNIX servers (note this is handled internall by tt(zftp)). If var(dir)
|
||||
is omitted, has the effect of tt(zfcd ~).
|
||||
|
||||
The second form changes to the directory previously current.
|
||||
|
||||
The third form attempts to change the current directory by replacing the
|
||||
first occurrence of the string var(old) with the string var(new) in the
|
||||
current directory.
|
||||
|
||||
Note that in this command, and indeed anywhere a remote filename is
|
||||
expected, the string which on the local host corresponds to tt(~) is
|
||||
converted back to a tt(~) before being passed to the remote machine.
|
||||
This is convenient because of the way expansion is performed on the command
|
||||
line before tt(zfcd) receives a string. For example, suppose the command
|
||||
is tt(zfcd ~/foo). The shell will expand this to a full path as in tt(zfcd
|
||||
/home/user2/pws/foo). At this stage, tt(zfcd) recognises the initial path
|
||||
as tt(~), and the directory sent to the remote host is tt(~/foo), so that
|
||||
the tt(~) will be expanded by the server to the correct remote host
|
||||
directory. Other named directories of the form tt(~name) are not treated
|
||||
in this fashion.
|
||||
)
|
||||
item(tt(zfhere))(
|
||||
Change directory on the remote server to the one corresponding to the
|
||||
current local directory, with special handling of tt(~) as in tt(zfcd).
|
||||
For example, if the current local directory is tt(~/foo/bar), then
|
||||
tt(zfhere) performs the effect of tt(zfcd ~/foo/bar).
|
||||
)
|
||||
item(tt(zfdir [ -rfd ] [ - ] [ var(dir-options) ] [ var(dir) ]))(
|
||||
Produce a long directory listing. The arguments var(dir-options) and
|
||||
var(dir) are passed directly to the server and their effect is
|
||||
implementation dependent, but specifying a particular remote directory
|
||||
var(dir) is usually possible. The output is passed through pager.
|
||||
|
||||
The directory is usually cached for re-use. In fact, two caches are
|
||||
maintained. One is for use when there is no var(dir-options) or var(dir),
|
||||
i.e. a full listing of the current remote directory; it is flushed
|
||||
when the current remote directory changes. The other is
|
||||
kept for repeated use of tt(zfdir) with the same arguments; for example,
|
||||
repeated use of tt(zfdir /pub/gnu) will only require the directory to be
|
||||
retrieved on the first call. Alternatively, this cache can be re-viewed with
|
||||
the tt(-r) option. As relative directories will confuse
|
||||
tt(zfdir), the tt(-f) option can be used to force the cache to be flushed.
|
||||
Also, the option tt(-d) will delete both caches without showing a directory
|
||||
listing.
|
||||
)
|
||||
item(tt(zfls) [ var(ls-options) ] [ var(dir) ])(
|
||||
List files on the remote server. With no arguments, this will produce a
|
||||
simple list of file names for the current remote directory. Any arguments
|
||||
are passed directory to the server. No pager and no caching is used.
|
||||
)
|
||||
enditem()
|
||||
|
||||
subsect(Status commands)
|
||||
startitem()
|
||||
item(tt(zftype) [ var(type) ])(
|
||||
With no arguments, show the type of data to be transferred, usually ASCII
|
||||
or binary. With an argument, change the type: the types tt(A) or
|
||||
tt(ASCII) for ASCII data and tt(B) or tt(BINARY), tt(I) or tt(IMAGE) for
|
||||
binary data are understood case-insensitively.
|
||||
)
|
||||
item(tt(zfstat) [ -v ])(
|
||||
Show the status of the current or last connection, as well as the status of
|
||||
some of tt(zftp)'s status variables. With the tt(-v) option, a more
|
||||
verbose listing is produced by querying the server for its version of
|
||||
events, too.
|
||||
)
|
||||
enditem()
|
||||
|
||||
subsect(Retrieving files)
|
||||
The commands for retrieving files all take at least two options. tt(-G)
|
||||
suppresses remote filename expansion which would otherwise be performed
|
||||
(see below for a more detailed description of that). tt(-t) attempts
|
||||
to set the modification time of the local file to that of the remote file:
|
||||
this requires version 5 of tt(perl), see the description of the function
|
||||
tt(zfrtime) below for more information.
|
||||
|
||||
startitem()
|
||||
item(tt(zfget [ -Gt ] var(file1) ...))(
|
||||
Retrieve all the listed files var(file1) ... one at a time from the remote
|
||||
server. If a file contains a `tt(/)', the full name is passed to the
|
||||
remote server, but the file is stored locally under the name given by the
|
||||
part after the final `tt(/)'.
|
||||
)
|
||||
item(tt(zfuget [ -Gvst ] var(file1) ...))(
|
||||
As tt(zfget), but only retrieve files where the version on the remote
|
||||
server is newer (has a later modification time), or where the local file
|
||||
does not exist. If the remote file is older but the files have different
|
||||
sizes, or if the sizes are the same but the remote file is newer, the user
|
||||
will usually be queried. With the option tt(-s), the command runs silently
|
||||
and will always retrieve the file in either of those two cases. With the
|
||||
option tt(-v), the command prints more information about the files while it
|
||||
is working out whether or not to transfer them.
|
||||
)
|
||||
item(tt(zfcget [ -Gt ] var(file1) ...))(
|
||||
As tt(zfget), but if any of the local files exists, and is shorter than
|
||||
the corresponding remote file, the command assumes that it is the result of
|
||||
a partially completed transfer and attempts to transfer the rest of the
|
||||
file. This is useful on a poor connection which keeps failing.
|
||||
|
||||
Note that this requires a commonly implemented, but non-standard, version
|
||||
of the FTP protocol, so is not guaranteed to work on all servers.
|
||||
)
|
||||
xitem(tt(zfgcp [ -Gt ] var(remote-file) var(local-file)))
|
||||
item(tt(zfgcp [ -Gt ] var(rfile1) ... var(ldir)))(
|
||||
This retrieves files from the remote server with arguments behaving
|
||||
similarly to the tt(cp) command.
|
||||
|
||||
In the first form, copy var(remote-file) from the server to the local file
|
||||
var(local-file).
|
||||
|
||||
In the second form, copy all the remote files var(rfile1) ... into the
|
||||
local directory var(ldir) retaining the same basenames. This assumes UNIX
|
||||
directory semantics.
|
||||
)
|
||||
enditem()
|
||||
|
||||
subsect(Sending files)
|
||||
startitem()
|
||||
item(tt(zfput var(file1) ...))(
|
||||
Send all the var(file1) ... given separately to the remote server. If a
|
||||
filename contains a `tt(/)', the full filename is used locally to find the
|
||||
file, but only the basename is used for the remote file name.
|
||||
)
|
||||
item(tt(zfuput [ -vs ] var(file1) ...))(
|
||||
As tt(zfput), but only send files which are newer than their local
|
||||
equivalents, or if the remote file does not exist. The logic is the same
|
||||
as for tt(zfuget), but reversed between local and remote files.
|
||||
)
|
||||
item(tt(zfcput var(file1) ...))(
|
||||
As tt(zfput), but if any remote file already exists and is shorter than the
|
||||
local equivalent, assume it is the result of an incomplete transfer and
|
||||
send the rest of the file to append to the existing part. As the FTP
|
||||
append command is part of the standard set, this is in principle more
|
||||
likely to work than tt(zfcget).
|
||||
)
|
||||
xitem(tt(zfpcp var(local-file) var(remote-file)))
|
||||
item(tt(zfpcp var(lfile1) ... var(rdir)))(
|
||||
This sends files to the remote server with arguments behaving similarly to
|
||||
the tt(cp) command.
|
||||
|
||||
With two arguments, copy var(local-file) to the server as
|
||||
var(remote-file).
|
||||
|
||||
With more than two arguments, copy all the local files var(lfile1) ... into
|
||||
the existing remote directory var(rdir) retaining the same basenames. This
|
||||
assumes UNIX directory semantics.
|
||||
|
||||
A problem arises if you attempt to use tt(zfpcp) var(lfile1) var(rdir),
|
||||
i.e. the second form of copying but with two arguments, as the command has
|
||||
no simple way of knowing if var(rdir) corresponds to a directory or a
|
||||
filename. It attempts to resolve this in various ways. First, if the
|
||||
var(rdir) argument is tt(.) or tt(..) or ends in a slash, it is assumed to
|
||||
be a directory. Secondly, if the operation of copying to a remote file in
|
||||
the first form failed, and the remote server sends back the expected
|
||||
failure code 553 and a reply including the string `tt(Is a directory)',
|
||||
then tt(zfpcp) will retry using the second form.
|
||||
)
|
||||
enditem()
|
||||
|
||||
subsect(Closing the connectino)
|
||||
startitem()
|
||||
item(tt(zfclose))(
|
||||
Close the connection.
|
||||
)
|
||||
enditem()
|
||||
|
||||
subsect(Other functions)
|
||||
Mostly, these functions will not be called directly (apart from
|
||||
tt(zfinit)), but are described here for completeness. You may wish to
|
||||
alter tt(zftp_chpwd) and tt(zftp_progress), in particular.
|
||||
|
||||
startitem()
|
||||
item(tt(zfinit [ -n ]))(
|
||||
As decribed above, this is used to initialise the zftp function system.
|
||||
The tt(-n) option should be used if the zftp command is already built into
|
||||
the shell.
|
||||
)
|
||||
item(tt(zfautocheck [ -dn ]))(
|
||||
This function is called to implement automatic reopening behaviour, as
|
||||
described in more detail below. The options must appear in the first
|
||||
argument; tt(-n) prevents the command from changing to the old directory,
|
||||
while tt(-d) prevents it from setting the variable tt(do_close), which it
|
||||
otherwise does as a flag for automatically closing the connection after a
|
||||
transfer. The host and directory for the last session are stored in the
|
||||
variable tt($zflastsession), but the internal host/user/password parameters
|
||||
must also be correctly set.
|
||||
)
|
||||
item(tt(zfcd_match var(prefix) var(suffix)))(
|
||||
This performs matching for completion of remote directory names. If the
|
||||
remote server is UNIX, it will attempt to persuade the server to list the
|
||||
remote directory with subdirectories marked, which usually works but is not
|
||||
guaranteed. On other hosts it simply calls tt(zfget_match) and hence
|
||||
completes all files, not just directories. On some systems, directories
|
||||
may not even look like filenames.
|
||||
)
|
||||
item(tt(zfget_match var(prefix) var(suffix)))(
|
||||
This performs matching for completion of remote filenames. It caches files
|
||||
for the current directory (only) in the shell parameter tt($zftp_fcache).
|
||||
It is in the form to be called by the tt(-K) option of tt(compctl), but
|
||||
also works when called from a widget-style completion function with
|
||||
var(prefix) and var(suffix) set appropriately.
|
||||
)
|
||||
item(tt(zfrglob var(varname)))(
|
||||
Perform remote globbing, as describes in more detail below. var(varname)
|
||||
is the name of a variable containing the pattern to be expanded; if there
|
||||
were any matches, the same variable will be set to the exanded set of
|
||||
filenames on return.
|
||||
)
|
||||
item(tt(zfrtime var(lfile) var(rfile) [ var(time) ]))(
|
||||
Set the local file var(lfile) to have the same modification time as the
|
||||
remote file var(rfile), or the explicit time var(time) in FTP format
|
||||
tt(CCYYMMDDhhmmSS) for the GMT timezone.
|
||||
|
||||
Currently this requires tt(perl) version 5 to perform the conversion from
|
||||
GMT to local time. This is unfortunately difficult to do using shell code
|
||||
alone.
|
||||
)
|
||||
item(tt(zftp_chpwd))(
|
||||
This function is called every time a connection is opened, or closed, or
|
||||
the remote directory changes. This version alters the title bar of an
|
||||
tt(xterm) or tt(sun-cmd) terminal emulator to reflect the local and remote
|
||||
hostnames and current directories. It works best when combined with the
|
||||
function tt(chpwd). In particular, a function of the form
|
||||
|
||||
tt(indent(
|
||||
nofill(chpwd() {)
|
||||
nofill( if [[ -n $ZFTP_USER ]]; then)
|
||||
nofill( zftp_chpwd)
|
||||
nofill( else)
|
||||
nofill( # usual chpwd e.g put host:directory in title bar)
|
||||
nofill( fi)
|
||||
nofill(})
|
||||
))
|
||||
|
||||
fits in well.
|
||||
)
|
||||
item(tt(zftp_progress))(
|
||||
This function shows the status of the transfer as the percentage of the
|
||||
total so far transferred. It will not write anything unless the output is
|
||||
going to a terminal; however, if you transfer files in the background, you
|
||||
should tt(unfunction) this first. (Background file transfers don't work on
|
||||
all OSes.) Note also that if you alter it, any output em(must) be to
|
||||
standard error, as standard output may be a file being received.
|
||||
)
|
||||
enditem()
|
||||
|
||||
texinode(Miscellaneous Features)()(Zftp Functions)(Zftp Function System)
|
||||
sect(Miscellaneous Features)
|
||||
|
||||
subsect(Remote globbing)
|
||||
|
||||
The commands for retrieving files usually perform filename expansion
|
||||
(globbing) on their arguments; this can be turned off by passing the option
|
||||
tt(-G) to each of the commands. Normally this operates by retrieving a
|
||||
complete list of files for the directory in question, then matching these
|
||||
locally against the pattern supplied. This has the advantage that the full
|
||||
range of zsh patterns (respecting the setting of the option
|
||||
tt(EXTENDED_GLOB)) can be used. However, it means that the directory part
|
||||
of a filename will not be expanded and must be given exactly. If the
|
||||
remote server does not support the UNIX directory semantics, directory
|
||||
handling is problematic and it is recommended that globbing only be used
|
||||
within the current directory. The list of files in the current directory,
|
||||
if retrieved, will be cached, so that subsequent globs in the same
|
||||
directory without an interventing tt(zfcd) are fast.
|
||||
|
||||
If the variable tt($zfrglob) is set to a non-zero length, globbing is
|
||||
instead performed on the remote host: the server is asked for a list of
|
||||
matching files. This is highly dependent on how the server is implemented,
|
||||
though typically UNIX servers will provide support for basic glob
|
||||
patterns. This may in some cases be faster, as it avoids retrieving the
|
||||
entire list of directory contents.
|
||||
|
||||
subsect(Automatic and temporary reopening)
|
||||
|
||||
As described for the tt(zfopen) command, a subsequent tt(zfopen) with no
|
||||
parameters will reopen the connection to the last host (this includes
|
||||
connections made with the tt(zfanon) command). Opened in this fashion, the
|
||||
connection starts in the default remote directory and will remain open
|
||||
until explicitly closed.
|
||||
|
||||
Automatic re-opening is also available. If a connection is not currently
|
||||
open and a command requiring a connection is given, the last connection is
|
||||
implicitly reopened. In this case the directory which was current when the
|
||||
connection was closed again becomes the current directory (unless, of
|
||||
course, the command given changes it). Automatic reopening will also take
|
||||
place if the connection was close by the remote server for whatever reason
|
||||
(e.g. a timeout). It is not available if the tt(-1) option to tt(zfopen)
|
||||
or tt(zfanon) was used.
|
||||
|
||||
Furthermore, if the command issued is a file transfer, the connection will
|
||||
be closed after the transfer is finished, hence providing a one-shot mode
|
||||
for transfers. This does not apply to directory changing or listing
|
||||
commands; for example a tt(zfdir) may reopen a connection but will leave it
|
||||
open. Also, automatic closure will only ever happen in the same command as
|
||||
automatic opening, i.e a tt(zfdir) directly followed by a tt(zfget) will
|
||||
never close the connection automatically.
|
||||
|
||||
Information about the previous connection is given by the tt(zfstat)
|
||||
function. So, for example, if that reports:
|
||||
|
||||
tt(indent(
|
||||
nofill(Not connected.)
|
||||
nofill(Last session: ftp.bar.com:/pub/textfiles)
|
||||
))
|
||||
|
||||
then the command tt(zfget file.txt) will attempt to reopen a connection to
|
||||
tt(ftp.bar.com), retrieve the file tt(/pub/textfiles/file.txt), and
|
||||
immediately close the connection again. On the other hand, tt(zfcd ..)
|
||||
will open the connection in the directory tt(/pub) and leave it open.
|
||||
|
||||
subsect(Completion)
|
||||
|
||||
Completion of remote files and directories is supported. The older,
|
||||
tt(compctl)-style completion is defined when tt(zfinit) is called; support
|
||||
for the new widget-based completion system is provided in the function
|
||||
tt(Completion/Builtins/_zftp), which should be installed with the other
|
||||
functions of the completion system and hence should automatically be
|
||||
available.
|
0
Doc/zshzftpsys.yo
Normal file
0
Doc/zshzftpsys.yo
Normal file
4
Functions/Zftp/README
Normal file
4
Functions/Zftp/README
Normal file
|
@ -0,0 +1,4 @@
|
|||
This directory contains a set of functions acting as a front end to the
|
||||
zftp command, provided as an add-on module. They allow you to perform FTP
|
||||
tasks from within the shell using as many of the shell's own facilities
|
||||
as possible. For more information, see the zshzftpsys manual page.
|
70
Functions/Zftp/zfanon
Normal file
70
Functions/Zftp/zfanon
Normal file
|
@ -0,0 +1,70 @@
|
|||
# function zfanon {
|
||||
|
||||
emulate -L zsh
|
||||
|
||||
local opt optlist once
|
||||
|
||||
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
|
||||
1) once=1
|
||||
;;
|
||||
*) print option $opt not recognised >&2
|
||||
;;
|
||||
esac
|
||||
done
|
||||
shift
|
||||
done
|
||||
|
||||
if [[ -z $EMAIL_ADDR ]]; then
|
||||
# Exercise in futility. There's a poem by Wallace Stevens
|
||||
# called something like `N ways of looking at a blackbird',
|
||||
# where N is somewhere around 0x14 to 0x18. Now zftp is
|
||||
# ashamed to prsent `N ways of looking at a hostname'.
|
||||
local domain host
|
||||
# First, maybe we've already got it. Zen-like.
|
||||
if [[ $HOST = *.* ]]; then
|
||||
# assume this is the full host name
|
||||
host=$HOST
|
||||
elif [[ -f /etc/resolv.conf ]]; then
|
||||
# Next, maybe we've got resolv.conf.
|
||||
domain=$(awk '/domain/ { print $2 }' /etc/resolv.conf)
|
||||
[[ -n $domain ]] && host=$HOST.$domain
|
||||
fi
|
||||
# Next, maybe we've got nlsookup. May not work on LINUX.
|
||||
[[ -z $host ]] && host=$(nslookup $HOST | awk '/Name:/ { print $2 }')
|
||||
if [[ -z $host ]]; then
|
||||
# we're running out of ideas, but this should work.
|
||||
# after all, i wrote it...
|
||||
# don't want user to know about this, too embarrassed.
|
||||
local oldvb=$ZFTP_VERBOSE oldtm=$ZFTP_TMOUT
|
||||
ZFTP_VERBOSE=
|
||||
ZFTP_TMOUT=5
|
||||
if zftp open $host >& /dev/null; then
|
||||
host=$ZFTP_HOST
|
||||
zftp close $host
|
||||
fi
|
||||
ZFTP_VERBOSE=$oldvb
|
||||
ZFTP_TMOUT=$oldtm
|
||||
fi
|
||||
if [[ -z $host ]]; then
|
||||
print "Can't get your hostname. Define \$EMAIL_ADDR by hand."
|
||||
return 1;
|
||||
fi
|
||||
EMAIL_ADDR="$USER@$host"
|
||||
print "Using $EMAIL_ADDR as anonymous FTP password."
|
||||
fi
|
||||
|
||||
if [[ $once = 1 ]]; then
|
||||
zftp open $1 anonymous $EMAIL_ADDR
|
||||
else
|
||||
zftp params $1 anonymous $EMAIL_ADDR
|
||||
zftp open
|
||||
fi
|
||||
# }
|
33
Functions/Zftp/zfautocheck
Normal file
33
Functions/Zftp/zfautocheck
Normal file
|
@ -0,0 +1,33 @@
|
|||
# function zfautocheck {
|
||||
# This function is used to implement auto-open behaviour.
|
||||
#
|
||||
# With first argument including n, don't change to the old directory; else do.
|
||||
#
|
||||
# Set do_close to 1 if the connection was not previously open, 0 otherwise
|
||||
# With first arguemnt including d, don't set do_close to 1. Broadly
|
||||
# speaking, we use this mechanism to shut the connection after use
|
||||
# if the connection had been explicitly closed (i.e. didn't time out,
|
||||
# which zftp test investigates) and we are not using a directory
|
||||
# command, which implies we are looking for something so should stay open
|
||||
# for it.
|
||||
|
||||
# Remember the old session: zflastsession will be overwritten by
|
||||
# a successful open.
|
||||
local lastsession=$zflastsession
|
||||
|
||||
if [[ -z $ZFTP_HOST ]]; then
|
||||
zfopen || return 1
|
||||
[[ $1 = *d* ]] || do_close=1
|
||||
elif zftp test 2>/dev/null; then
|
||||
return 0
|
||||
else
|
||||
zfopen || return 1
|
||||
fi
|
||||
|
||||
if [[ $1 = *n* ]]; then
|
||||
return 0
|
||||
elif [[ -n $lastsession && $ZFTP_HOST = ${lastsession%%:*} ]]; then
|
||||
zfcd ${lastsession#*:}
|
||||
fi
|
||||
|
||||
# }
|
52
Functions/Zftp/zfcd
Normal file
52
Functions/Zftp/zfcd
Normal file
|
@ -0,0 +1,52 @@
|
|||
# function zfcd {
|
||||
# zfcd: change directory on the remote server.
|
||||
#
|
||||
# Currently has the following features:
|
||||
# --- an initial string matching $HOME in the directory is turned back into ~
|
||||
# to be re-interpreted by the remote server.
|
||||
# --- zfcd with no arguments changes directory to '~'
|
||||
# --- `zfcd old new' and `zfcd -' work analagously to cd
|
||||
# --- if the connection is not currently open, it will try to
|
||||
# re-open it with the stored parameters as set by zfopen.
|
||||
# If the connection timed out, however, it won't know until
|
||||
# too late. In that case, just try the same zfcd command again
|
||||
# (but now `zfcd -' and `zfcd old new' won't work).
|
||||
|
||||
# hack: if directory begins with $HOME, turn it back into ~
|
||||
# there are two reasons for this:
|
||||
# first, a ~ on the command line gets expanded even with noglob.
|
||||
# (I suppose this is correct, but I wouldn't like to swear to it.)
|
||||
# second, we can no do 'zfcd $PWD' and the like, and that will
|
||||
# work just as long as the directory structures under the home match.
|
||||
|
||||
emulate -L zsh
|
||||
|
||||
if [[ $1 = /* ]]; then
|
||||
zfautocheck -dn
|
||||
else
|
||||
zfautocheck -d
|
||||
fi
|
||||
|
||||
if [[ $1 = $HOME || $1 = $HOME/* ]]; then
|
||||
1="~${1#$HOME}"
|
||||
fi
|
||||
|
||||
if (( $# == 0 )); then
|
||||
# Emulate `cd' behaviour
|
||||
set -- '~'
|
||||
elif [[ $# -eq 1 && $1 = - ]]; then
|
||||
# Emulate `cd -' behaviour.
|
||||
set -- $zflastdir
|
||||
elif [[ $# -eq 2 ]]; then
|
||||
# Emulate `cd old new' behaviour.
|
||||
# We have to find a character not in $1 or $2; ! is a good bet.
|
||||
eval set -- "\${ZFTP_PWD:s!$1!$2!}"
|
||||
fi
|
||||
|
||||
# We have to remember the current directory before changing it
|
||||
# if we want to keep it.
|
||||
local lastdir=$ZFTP_PWD
|
||||
|
||||
zftp cd "$@" && zflastdir=$lastdir
|
||||
print $zflastsession
|
||||
# }
|
42
Functions/Zftp/zfcd_match
Normal file
42
Functions/Zftp/zfcd_match
Normal file
|
@ -0,0 +1,42 @@
|
|||
# function zfcd_match {
|
||||
|
||||
emulate -L zsh
|
||||
|
||||
# see zfcd for details of this hack
|
||||
if [[ $1 = $HOME || $1 = $HOME/* ]]; then
|
||||
1="~${1#$HOME}"
|
||||
fi
|
||||
|
||||
# error messages only
|
||||
local ZFTP_VERBOSE=45
|
||||
# should we redirect 2>/dev/null or let the user see it?
|
||||
|
||||
local tmpf=${TMPPREFIX}zfcm$$
|
||||
|
||||
if [[ $ZFTP_SYSTEM = UNIX* ]]; then
|
||||
# hoo, aren't we lucky: this makes things so much easier
|
||||
setopt localoptions rcexpandparam
|
||||
local dir
|
||||
if [[ $1 = ?*/* ]]; then
|
||||
dir=${1%/*}
|
||||
elif [[ $1 = /* ]]; then
|
||||
dir=/
|
||||
fi
|
||||
# If we're using -F, we get away with using a directory
|
||||
# to list, but not a glob. Don't ask me why.
|
||||
# I hate having to rely on awk here.
|
||||
zftp ls -F $dir >$tmpf
|
||||
reply=($(awk '/\/$/ { print substr($1, 0, length($1)-1) }' $tmpf))
|
||||
rm -f $tmpf
|
||||
if [[ $dir = / ]]; then
|
||||
reply=(${dir}$reply)
|
||||
elif [[ -n $dir ]]; then
|
||||
reply=($dir/$reply)
|
||||
fi
|
||||
else
|
||||
# I simply don't know what to do here.
|
||||
# Just use the list of files for the current directory.
|
||||
zfget_match $*
|
||||
fi
|
||||
|
||||
# }
|
87
Functions/Zftp/zfcget
Normal file
87
Functions/Zftp/zfcget
Normal file
|
@ -0,0 +1,87 @@
|
|||
# function zfcget {
|
||||
# Continuation get of files from remote server.
|
||||
# For each file, if it's shorter here, try to get the remainder from
|
||||
# over there. This requires the server to support the REST command
|
||||
# in the way many do but RFC959 doesn't specify.
|
||||
# Options:
|
||||
# -G don't to remote globbing, else do
|
||||
# -t 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 stat=0 optlist opt nglob remlist locst remst
|
||||
local tmpfile=${TMPPREFIX}zfcget$$ rstat tsize time
|
||||
|
||||
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
|
||||
G) nglob=1
|
||||
;;
|
||||
t) time=1
|
||||
;;
|
||||
*) print option $opt not recognised >&2
|
||||
;;
|
||||
esac
|
||||
done
|
||||
shift
|
||||
done
|
||||
|
||||
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}
|
||||
if [[ ! -f $loc ]]; then
|
||||
# File does not yet exist
|
||||
zftp get $rem >$loc || stat=$?
|
||||
else
|
||||
# Compare the sizes.
|
||||
locst=($(zftp local $loc))
|
||||
zftp remote $rem >$tmpfile
|
||||
rstat=$?
|
||||
remst=($(<$tmpfile))
|
||||
rm -f $tmpfile
|
||||
if [[ $rstat = 2 ]]; then
|
||||
print "Server does not support SIZE command.\n" \
|
||||
"Assuming you know what you're doing..." 2>&1
|
||||
zftp getat $rem $locst[1] >>$loc || stat=$?
|
||||
continue
|
||||
elif [[ $rstat = 1 ]]; then
|
||||
print "Remote file not found: $rem" 2>&1
|
||||
continue
|
||||
fi
|
||||
if [[ $locst[1] -gt $remst[1] ]]; then
|
||||
print "Local file is larger!" 2>&1
|
||||
continue;
|
||||
elif [[ $locst[1] == $remst[1] ]]; then
|
||||
print "Files are already the same size." 2>&1
|
||||
continue
|
||||
else
|
||||
if zftp getat $rem $locst[1] >>$loc; then
|
||||
[[ $time = 1 ]] && zfrtime $loc $rem $remst[2]
|
||||
else
|
||||
stat=1
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
done
|
||||
fi
|
||||
done
|
||||
|
||||
return $stat
|
||||
# }
|
3
Functions/Zftp/zfclose
Normal file
3
Functions/Zftp/zfclose
Normal file
|
@ -0,0 +1,3 @@
|
|||
# function zfclose {
|
||||
zftp close
|
||||
# }
|
76
Functions/Zftp/zfcput
Normal file
76
Functions/Zftp/zfcput
Normal file
|
@ -0,0 +1,76 @@
|
|||
# function zfcput {
|
||||
# Continuation put of files from remote server.
|
||||
# For each file, if it's shorter over there, put the remainder from
|
||||
# over here. This uses append, which is standard, so unlike zfcget it's
|
||||
# expected to work on any reasonable server... err, as long as it
|
||||
# supports SIZE and MDTM. (It could be enhanced so you can enter the
|
||||
# size so far by hand.) You should probably be in binary transfer
|
||||
# mode, thought it's not enforced.
|
||||
#
|
||||
# To read from midway through a local file, `tail +<n>c' is used.
|
||||
# It would be nice to find a way of doing this which works on all OS's.
|
||||
|
||||
emulate -L zsh
|
||||
|
||||
local loc rem stat=0 locst remst offs tailtype
|
||||
local tmpfile=${TMPPREFIX}zfcget$$ rstat
|
||||
|
||||
# find how tail works. this is intensely annoying, since it's completely
|
||||
# standard in C. od's no use, since we can only skip whole blocks.
|
||||
if [[ $(echo abcd | tail +2c) = bcd ]]; then
|
||||
tailtype=c
|
||||
elif [[ $(echo abcd | tail --bytes=+2) = bcd ]]; then
|
||||
tailtype=b
|
||||
else
|
||||
print "I can't get your \`tail' to start from from arbitrary characters.\n" \
|
||||
"If you know how to do this, let me know." 2>&1
|
||||
return 1
|
||||
fi
|
||||
|
||||
for loc in $*; do
|
||||
# zfcd directory hack to put the front back to ~
|
||||
rem=$loc
|
||||
if [[ $rem = $HOME || $rem = $HOME/* ]]; then
|
||||
rem="~${rem#$HOME}"
|
||||
fi
|
||||
if [[ ! -r $loc ]]; then
|
||||
print "Can't read file $loc"
|
||||
stat=1
|
||||
else
|
||||
# Compare the sizes.
|
||||
locst=($(zftp local $loc))
|
||||
zftp remote $rem >$tmpfile
|
||||
rstat=$?
|
||||
remst=($(<$tmpfile))
|
||||
rm -f $tmpfile
|
||||
if [[ $rstat = 2 ]]; then
|
||||
print "Server does not support remote status commands.\n" \
|
||||
"You will have to find out the size by hand and use zftp append." 2>&1
|
||||
stat=1
|
||||
continue
|
||||
elif [[ $rstat = 1 ]]; then
|
||||
# Not found, so just do a standard put.
|
||||
zftp put $rem <$loc
|
||||
elif [[ $remst[1] -gt $locst[1] ]]; then
|
||||
print "Remote file is larger!" 2>&1
|
||||
continue;
|
||||
elif [[ $locst[1] == $remst[1] ]]; then
|
||||
print "Files are already the same size." 2>&1
|
||||
continue
|
||||
else
|
||||
# tail +<N>c takes the count of the character
|
||||
# to start from, not the offset from zero. if we did
|
||||
# this with years, then 2000 would be 1999. no y2k bug!
|
||||
# brilliant.
|
||||
(( offs = $remst[1] + 1 ))
|
||||
if [[ $tailtype = c ]]; then
|
||||
tail +${offs}c $loc | zftp append $rem || stat=1
|
||||
else
|
||||
tail --bytes=+$offs $loc | zftp append $rem || stat=1
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
return $stat
|
||||
# }
|
99
Functions/Zftp/zfdir
Normal file
99
Functions/Zftp/zfdir
Normal file
|
@ -0,0 +1,99 @@
|
|||
# function zfdir {
|
||||
# Long directory of remote server.
|
||||
# The remote directory is cached. In fact, two caches are kept:
|
||||
# one of the standard listing of the current directory, i.e. zfdir
|
||||
# with no arguments, and another for everything else.
|
||||
# To access the appropriate cache, just use zfdir with the same
|
||||
# arguments as previously. zfdir -r will also re-use the `everything
|
||||
# else' cache; you can always reuse the current directory cache just
|
||||
# with zfdir on its own.
|
||||
#
|
||||
# The current directory cache is emptied when the directory changes;
|
||||
# the other is kept until a new zfdir with a non-empty argument list.
|
||||
# Both are removed when the connection is closed.
|
||||
#
|
||||
# zfdir -f will force the existing cache to be ignored, e.g. if you know
|
||||
# or suspect the directory has changed.
|
||||
# zfdir -d will remove both caches without listing anything.
|
||||
# If you need to pass -r, -f or -d to the dir itself, use zfdir -- -d etc.;
|
||||
# unrecognised options are passed through to dir, but zfdir options must
|
||||
# appear first and unmixed with the others.
|
||||
|
||||
emulate -L zsh
|
||||
setopt extendedglob
|
||||
|
||||
local file opt optlist redir i newargs force
|
||||
|
||||
while [[ $1 = -* ]]; do
|
||||
if [[ $1 = - || $1 = -- ]]; then
|
||||
shift;
|
||||
break;
|
||||
elif [[ $1 != -[rfd]## ]]; then
|
||||
# pass options through to ls
|
||||
break;
|
||||
fi
|
||||
optlist=${1#-}
|
||||
for (( i = 1; i <= $#optlist; i++)); do
|
||||
opt=$optlist[$i]
|
||||
case $optlist[$i] in
|
||||
r) redir=1
|
||||
;;
|
||||
f) force=1
|
||||
;;
|
||||
d) [[ -n $zfcurdir && -f $zfcurdir ]] && rm -f $zfcurdir
|
||||
[[ -n $zfotherdir && -f $zfotherdir ]] && rm -f $zfotherdir
|
||||
zftp_fcache=()
|
||||
return 0
|
||||
;;
|
||||
esac
|
||||
done
|
||||
shift
|
||||
done
|
||||
|
||||
zfautocheck -d
|
||||
|
||||
# directory hack, see zfcd
|
||||
for (( i = 1; i <= $#argv; i++ )); do
|
||||
if [[ $argv[$i] = $HOME || $argv[$i] = $HOME/* ]]; then
|
||||
argv[$i]="~${argv[$i]#$HOME}"
|
||||
fi
|
||||
done
|
||||
|
||||
if [[ $# -eq 0 ]]; then
|
||||
# Cache it in the current directory file. This means that repeated
|
||||
# calls to zfdir with no arguments always use a cached file.
|
||||
[[ -z $zfcurdir ]] && zfcurdir=${TMPPREFIX}zfcurdir$$
|
||||
file=$zfcurdir
|
||||
else
|
||||
# Last directly looked at was not the current one, or at least
|
||||
# had non-standard arguments.
|
||||
[[ -z $zfotherdir ]] && zfotherdir=${TMPPREFIX}zfotherdir$$
|
||||
file=$zfotherdir
|
||||
newargs="$*"
|
||||
if [[ -f $file && $redir != 1 && $force -ne 1 ]]; then
|
||||
# Don't use the cached file if the arguments changed.
|
||||
[[ $newargs = $zfotherargs ]] || rm -f $file
|
||||
fi
|
||||
zfotherargs=$newargs
|
||||
fi
|
||||
|
||||
if [[ $force -eq 1 ]]; then
|
||||
rm -f $file
|
||||
# if it looks like current directory has changed, better invalidate
|
||||
# the filename cache, too.
|
||||
(( $# == 0 )) && zftp_fcache=()
|
||||
fi
|
||||
|
||||
if [[ -n $file && -f $file ]]; then
|
||||
eval ${PAGER:-more} \$file
|
||||
else
|
||||
if (zftp test); then
|
||||
# Works OK in subshells
|
||||
zftp dir $* | tee $file | eval ${PAGER-:more}
|
||||
else
|
||||
# Doesn't work in subshells (IRIX 6.2 --- why?)
|
||||
zftp dir $* >$file
|
||||
eval ${PAGER-:more} $file
|
||||
fi
|
||||
fi
|
||||
# }
|
83
Functions/Zftp/zfgcp
Normal file
83
Functions/Zftp/zfgcp
Normal file
|
@ -0,0 +1,83 @@
|
|||
# function zfgcp {
|
||||
# ZFTP get as copy: i.e. first arguments are remote, last is local.
|
||||
# Supposed to work exactly like a normal copy otherwise, i.e.
|
||||
# zfgcp rfile lfile
|
||||
# or
|
||||
# zfgcp rfile1 rfile2 rfile3 ... ldir
|
||||
# Options:
|
||||
# -G don't to remote globbing, else do
|
||||
# -t 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.
|
||||
#
|
||||
# If there is no current connection, try to use the existing set of open
|
||||
# parameters to establish one and close it immediately afterwards.
|
||||
|
||||
emulate -L zsh
|
||||
|
||||
local opt optlist nglob remlist rem loc time
|
||||
integer stat do_close
|
||||
|
||||
while [[ $1 == -* ]]; do
|
||||
if [[ $1 == - || $1 == -- ]]; then
|
||||
shift;
|
||||
break;
|
||||
fi
|
||||
optlist=${1#-}
|
||||
for (( i = 1; i <= $#optlist; i++)); do
|
||||
opt=$optlist[$i]
|
||||
case $opt in
|
||||
G) nglob=1
|
||||
;;
|
||||
t) time=1
|
||||
;;
|
||||
*) print option $opt not recognised >&2
|
||||
;;
|
||||
esac
|
||||
done
|
||||
shift
|
||||
done
|
||||
|
||||
zfautocheck
|
||||
|
||||
# hmm, we should really check this after expanding the glob,
|
||||
# but we shouldn't expand the last argument remotely anyway.
|
||||
if [[ $# -gt 2 && ! -d $argv[-1] ]]; then
|
||||
print "zfgcp: last argument must be a directory." 2>&1
|
||||
return 1
|
||||
elif [[ $# == 1 ]]; then
|
||||
print "zfgcp: not enough arguments." 2>&1
|
||||
return 1
|
||||
fi
|
||||
|
||||
if [[ -d $argv[-1] ]]; then
|
||||
local dir=$argv[-1]
|
||||
argv[-1]=
|
||||
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=$dir/${rem:t}
|
||||
if zftp get $rem >$loc; then
|
||||
[[ $time = 1 ]] && zfrtime $rem $loc
|
||||
else
|
||||
stat=1
|
||||
fi
|
||||
done
|
||||
fi
|
||||
done
|
||||
else
|
||||
zftp get $1 >$2 || stat=$?
|
||||
fi
|
||||
|
||||
(( $do_close )) && zfclose
|
||||
|
||||
return $stat
|
||||
# }
|
64
Functions/Zftp/zfget
Normal file
64
Functions/Zftp/zfget
Normal file
|
@ -0,0 +1,64 @@
|
|||
# function zfget {
|
||||
# Get files from remote server. Options:
|
||||
# -G don't to remote globbing, else do
|
||||
# -t 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.
|
||||
#
|
||||
# If the connection is not currently open, try to open it with the current
|
||||
# parameters (set by a previous zfopen or zfparams), then close it after
|
||||
# use. The file is put in the current directory (i.e. using the basename
|
||||
# of the remote file only); for more control, use zfgcp.
|
||||
|
||||
emulate -L zsh
|
||||
|
||||
local loc rem optlist opt nglob remlist time
|
||||
integer stat do_close
|
||||
|
||||
while [[ $1 == -* ]]; do
|
||||
if [[ $1 == - || $1 == -- ]]; then
|
||||
shift;
|
||||
break;
|
||||
fi
|
||||
optlist=${1#-}
|
||||
for (( i = 1; i <= $#optlist; i++)); do
|
||||
opt=$optlist[$i]
|
||||
case $opt in
|
||||
G) nglob=1
|
||||
;;
|
||||
t) time=1
|
||||
;;
|
||||
*) print option $opt not recognised >&2
|
||||
;;
|
||||
esac
|
||||
done
|
||||
shift
|
||||
done
|
||||
|
||||
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}
|
||||
if zftp get $rem >$loc; then
|
||||
[[ $time = 1 ]] && zfrtime $rem $loc
|
||||
else
|
||||
stat=1
|
||||
fi
|
||||
done
|
||||
fi
|
||||
done
|
||||
|
||||
(( $do_close )) && zfclose
|
||||
|
||||
return $stat
|
||||
# }
|
27
Functions/Zftp/zfget_match
Normal file
27
Functions/Zftp/zfget_match
Normal file
|
@ -0,0 +1,27 @@
|
|||
# function zfget_match {
|
||||
|
||||
emulate -L zsh
|
||||
|
||||
# the zfcd hack: this may not be necessary here
|
||||
if [[ $1 == $HOME || $1 == $HOME/* ]]; then
|
||||
1="~${1#$HOME}"
|
||||
fi
|
||||
|
||||
local tmpf=${TMPPREFIX}zfgm$$
|
||||
|
||||
if [[ $ZFTP_SYSTEM == UNIX* && $1 == */* ]]; then
|
||||
# On the first argument to ls, we usually get away with a glob.
|
||||
zftp ls "$1*$2" >$tmpf
|
||||
reply=($(<$tmpf))
|
||||
rm -f $tmpf
|
||||
else
|
||||
if (( $#zftp_fcache == 0 )); then
|
||||
# Always cache the current directory and use it
|
||||
# even if the system is UNIX.
|
||||
zftp ls >$tmpf
|
||||
zftp_fcache=($(<$tmpf))
|
||||
rm -f $tmpf
|
||||
fi
|
||||
reply=($zftp_fcache);
|
||||
fi
|
||||
# }
|
5
Functions/Zftp/zfhere
Normal file
5
Functions/Zftp/zfhere
Normal file
|
@ -0,0 +1,5 @@
|
|||
# function zfhere {
|
||||
# Change to the directory corresponding to $PWD on the server.
|
||||
# See zfcd for how this works.
|
||||
zfcd $PWD
|
||||
# }
|
28
Functions/Zftp/zfinit
Normal file
28
Functions/Zftp/zfinit
Normal file
|
@ -0,0 +1,28 @@
|
|||
[[ $1 = -n ]] || zmodload -ia zftp
|
||||
|
||||
alias zfcd='noglob zfcd'
|
||||
alias zfget='noglob zfget'
|
||||
alias zfls='noglob zfls'
|
||||
alias zfdir='noglob zfdir'
|
||||
alias zfuget='noglob zfuget'
|
||||
|
||||
# only way of getting that noglob out of the way: this is unnecessary with
|
||||
# widget-based completion and can be commented out.
|
||||
setopt completealiases
|
||||
|
||||
#
|
||||
# zftp completions: only use these if new-style completion is not
|
||||
# active.
|
||||
#
|
||||
if [[ ${#patcomps} -eq 0 || ${patcomps[(i)zf*]} -gt ${#patcomps} ]]; then
|
||||
compctl -f -x 'p[1]' \
|
||||
-k '(open params user login type ascii binary mode put putat
|
||||
get getat append appendat ls dir local remote mkdir rmdir delete
|
||||
close quit)' - \
|
||||
'w[1,cd][1,ls][1,dir][1,rmdir]' -K zfcd_match -S/ -q - \
|
||||
'W[1,get*]' -K zfget_match - 'w[1,delete][1,remote]' -K zfget_match - \
|
||||
'w[1,open][1,params]' -k hosts -- zftp
|
||||
compctl -K zfcd_match -S/ -q zfcd zfdir zfls
|
||||
compctl -K zfget_match zfget zfgcp zfuget zfcget
|
||||
compctl -k hosts zfanon zfopen zfparams
|
||||
fi
|
13
Functions/Zftp/zfls
Normal file
13
Functions/Zftp/zfls
Normal file
|
@ -0,0 +1,13 @@
|
|||
# function zfls {
|
||||
|
||||
emulate -L zsh
|
||||
|
||||
# directory hack, see zfcd
|
||||
if [[ $1 = $HOME || $1 = $HOME/* ]]; then
|
||||
1="~${1#$HOME}"
|
||||
fi
|
||||
|
||||
zfautocheck -d
|
||||
|
||||
zftp ls $*
|
||||
# }
|
42
Functions/Zftp/zfopen
Normal file
42
Functions/Zftp/zfopen
Normal file
|
@ -0,0 +1,42 @@
|
|||
# function zfopen {
|
||||
# Use zftp params to set parameters for open, rather than sending
|
||||
# them straight to open. That way they are stored for a future open
|
||||
# command.
|
||||
#
|
||||
# With option -1 (just this 1ce), don't do that.
|
||||
|
||||
emulate -L zsh
|
||||
|
||||
local optlist opt once
|
||||
|
||||
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
|
||||
1) once=1
|
||||
;;
|
||||
*) print option $opt not recognised >&2
|
||||
;;
|
||||
esac
|
||||
done
|
||||
shift
|
||||
done
|
||||
|
||||
# This is where we should try and do same name-lookupage in
|
||||
# both .netrc and .ncftp/bookmarks . We could even try saving
|
||||
# the info in their for new hosts, like ncftp does.
|
||||
|
||||
if [[ $once = 1 ]]; then
|
||||
zftp open $*
|
||||
else
|
||||
# set parameters, but only if there was at least a host
|
||||
(( $# > 0 )) && zfparams $*
|
||||
# now call with no parameters
|
||||
zftp open
|
||||
fi
|
||||
# }
|
12
Functions/Zftp/zfparams
Normal file
12
Functions/Zftp/zfparams
Normal file
|
@ -0,0 +1,12 @@
|
|||
# function zfparams {
|
||||
|
||||
emulate -L zsh
|
||||
|
||||
# Set to prompt for any user or password if not given.
|
||||
# Don't worry about accounts here.
|
||||
if (( $# > 0 )); then
|
||||
(( $# < 2 )) && 2='?'
|
||||
(( $# < 3 )) && 3='?'
|
||||
fi
|
||||
zftp params $*
|
||||
# }
|
47
Functions/Zftp/zfpcp
Normal file
47
Functions/Zftp/zfpcp
Normal file
|
@ -0,0 +1,47 @@
|
|||
# function zfpcp {
|
||||
# ZFTP put as copy: i.e. first arguments are remote, last is local.
|
||||
# Currently only supports
|
||||
# zfcp lfile rfile
|
||||
# if there are two arguments, or the second one is . or .., or ends
|
||||
# with a slash
|
||||
# or
|
||||
# zfcp lfile1 lfile2 lfile3 ... rdir
|
||||
# if there are more than two (because otherwise it doesn't
|
||||
# know if the last argument is a directory on the remote machine).
|
||||
# However, if the remote machine plays ball by telling us `Is a directory'
|
||||
# when we try to copy to a directory, zfpcp will then try to do the correct
|
||||
# thing.
|
||||
|
||||
emulate -L zsh
|
||||
|
||||
local rem loc
|
||||
integer stat do_close
|
||||
|
||||
zfautocheck
|
||||
|
||||
if [[ $# -gt 2 || $2 = (.|..) || $2 = */ ]]; then
|
||||
local dir=$argv[-1]
|
||||
argv[-1]=
|
||||
# zfcd directory hack to put the front back to ~
|
||||
if [[ $dir = $HOME || $dir = $HOME/* ]]; then
|
||||
dir="~${dir#$HOME}"
|
||||
fi
|
||||
[[ -n $dir && $dir != */ ]] || dir="$dir/"
|
||||
for loc in $*; do
|
||||
rem=$dir${loc:t}
|
||||
zftp put $rem <$loc || stat=1
|
||||
done
|
||||
else
|
||||
zftp put $2 <$1
|
||||
stat=$?
|
||||
if [[ stat -ne 0 && $ZFTP_CODE = 553 && $ZFTP_REPLY = *'Is a directory'* ]]
|
||||
then
|
||||
zftp put $2/$1:t <$1
|
||||
stat=$?
|
||||
fi
|
||||
fi
|
||||
|
||||
(( $do_close )) && zfclose
|
||||
|
||||
return $stat
|
||||
# }
|
23
Functions/Zftp/zfput
Normal file
23
Functions/Zftp/zfput
Normal file
|
@ -0,0 +1,23 @@
|
|||
# function zfput {
|
||||
# Simple put: dump every file under the same name, but stripping
|
||||
# off any directory parts to get the remote filename (i.e. always
|
||||
# goes into current remote directory). Use zfpcp to specify new
|
||||
# file name or new directory at remote end.
|
||||
|
||||
emulate -L zsh
|
||||
|
||||
local loc rem
|
||||
integer stat do_close
|
||||
|
||||
zfautocheck
|
||||
|
||||
for loc in $*; do
|
||||
rem=${loc:t}
|
||||
zftp put $rem <$loc
|
||||
[[ $? == 0 ]] || stat=$?
|
||||
done
|
||||
|
||||
(( $do_close )) && zfclose
|
||||
|
||||
return $stat
|
||||
# }
|
70
Functions/Zftp/zfrglob
Normal file
70
Functions/Zftp/zfrglob
Normal file
|
@ -0,0 +1,70 @@
|
|||
# function zfrglob {
|
||||
# Do the remote globbing for zfput, etc.
|
||||
# We have two choices:
|
||||
# (1) Get the entire file list and match it one by one
|
||||
# locally against the pattern.
|
||||
# Causes problems if we are globbing directories (rare, presumably).
|
||||
# But: we can cache the current directory, which
|
||||
# we need for completion anyway. Works on any OS if you
|
||||
# stick with a single directory. This is the default.
|
||||
# (2) Use remote globbing, i.e. pass it to ls at the site.
|
||||
# Faster, but only works with UNIX, and only basic globbing.
|
||||
# We do this if $zfrglob is non-null.
|
||||
|
||||
# There is only one argument, the variable containing the
|
||||
# pattern to be globbed. We set this back to an array containing
|
||||
# all the matches.
|
||||
|
||||
emulate -L zsh
|
||||
setopt extendedglob
|
||||
|
||||
local pat dir nondir files i
|
||||
|
||||
eval pat=\$$1
|
||||
|
||||
# Check if we really need to do anything. Look for standard
|
||||
# globbing characters, and if we are
|
||||
# using zsh for the actual pattern matching also look for
|
||||
# extendedglob characters.
|
||||
if [[ $pat != *[][*?]* &&
|
||||
( -n $zfrglob || $pat != *[(|)#^]* ) ]]; then
|
||||
return 0
|
||||
fi
|
||||
local tmpf=${TMPPREFIX}zfrglob$$
|
||||
|
||||
if [[ $zfrglob != '' ]]; then
|
||||
zftp ls "$pat" >$tmpf 2>/dev/null
|
||||
eval "$1=(\$(<\$tmpf))"
|
||||
rm -f $tmpf
|
||||
else
|
||||
if [[ $ZFTP_SYSTEM = UNIX* && $pat = */* ]]; then
|
||||
# not the current directory and we know how to handle paths
|
||||
if [[ $pat = ?*/* ]]; then
|
||||
# careful not to remove too many slashes
|
||||
dir=${pat%/*}
|
||||
else
|
||||
dir=/
|
||||
fi
|
||||
nondir=${pat##*/}
|
||||
zftp ls "$dir" 2>/dev/null >$tmpf
|
||||
files=($(<$tmpf))
|
||||
files=(${files:t})
|
||||
rm -f $tmpf
|
||||
else
|
||||
# we just have to do an ls and hope that's right
|
||||
nondir=$pat
|
||||
if (( $#zftp_fcache == 0 )); then
|
||||
# Why does `zftp_fcache=($(zftp ls))' sometimes not work?
|
||||
zftp ls >$tmpf
|
||||
zftp_fcache=($(<$tmpf))
|
||||
rm -f $tmpf
|
||||
fi
|
||||
files=($zftp_fcache)
|
||||
fi
|
||||
# now we want to see which of the $files match $nondir:
|
||||
# ${...:/foo} deletes occurrences of foo matching a complete word,
|
||||
# while the ^ inverts the sense so that anything not matching the
|
||||
# pattern in $nondir is excluded.
|
||||
eval "$1=(\${files:/^\${~nondir}})"
|
||||
fi
|
||||
# }
|
45
Functions/Zftp/zfrtime
Normal file
45
Functions/Zftp/zfrtime
Normal file
|
@ -0,0 +1,45 @@
|
|||
# function zfrtime {
|
||||
# Set the modification time of file LOCAL to that of REMOTE.
|
||||
# If the optional TIME is passed, it should be in the FTP format
|
||||
# CCYYMMDDhhmmSS, i.e. no dot before the seconds, and in GMT.
|
||||
# This is what both `zftp remote' and `zftp local' return.
|
||||
#
|
||||
# Unfortunately, since the time returned from FTP is GMT and
|
||||
# your file needs to be set in local time, we need to do some
|
||||
# hacking around with time. At the moment this requires perl 5
|
||||
# with the standard library.
|
||||
|
||||
emulate -L zsh
|
||||
|
||||
local time gmtime loctime
|
||||
|
||||
if [[ -n $3 ]]; then
|
||||
time=$3
|
||||
else
|
||||
time=($(zftp remote $2 2>/dev/null))
|
||||
[[ -n $time ]] && time=$time[2]
|
||||
fi
|
||||
[[ -z $time ]] && return 1
|
||||
|
||||
# Now's the real *!@**!?!. We have the date in GMT and want to turn
|
||||
# it into local time for touch to handle. It's just too nasty
|
||||
# to handle in zsh; do it in perl.
|
||||
if perl -mTime::Local -e '($file, $t) = @ARGV;
|
||||
$yr = substr($t, 0, 4) - 1900;
|
||||
$mon = substr($t, 4, 2) - 1;
|
||||
$mday = substr($t, 6, 2) + 0;
|
||||
$hr = substr($t, 8, 2) + 0;
|
||||
$min = substr($t, 10, 2) + 0;
|
||||
$sec = substr($t, 12, 2) + 0;
|
||||
$time = Time::Local::timegm($sec, $min, $hr, $mday, $mon, $yr);
|
||||
utime $time, $time, $file and return 0;' $1 $time 2>/dev/null; then
|
||||
print "Setting time for $1 failed. Need perl 5." 2>1
|
||||
fi
|
||||
|
||||
# If it wasn't for the GMT/local time thing, it would be this simple.
|
||||
#
|
||||
# time="${time[1,12]}.${time[13,14]}"
|
||||
#
|
||||
# touch -t $time $1
|
||||
|
||||
# }
|
89
Functions/Zftp/zfstat
Normal file
89
Functions/Zftp/zfstat
Normal file
|
@ -0,0 +1,89 @@
|
|||
# function zfstat {
|
||||
# Give a zftp status report using local variables.
|
||||
# With option -v, connect to the remote host and ask it what it
|
||||
# thinks the status is.
|
||||
|
||||
setopt localoptions unset
|
||||
unsetopt ksharrays
|
||||
|
||||
local i stat=0 opt optlist verbose
|
||||
|
||||
while [[ $1 = -* ]]; do
|
||||
if [[ $1 = - || $1 = -- ]]; then
|
||||
shift;
|
||||
break;
|
||||
fi
|
||||
optlist=${1#-}
|
||||
for (( i = 1; i <= $#optlist; i++)); do
|
||||
opt=$optlist[$i]
|
||||
case $opt in
|
||||
v) verbose=1
|
||||
;;
|
||||
*) print option $opt not recognised >&2
|
||||
;;
|
||||
esac
|
||||
done
|
||||
shift
|
||||
done
|
||||
|
||||
if [[ -n $ZFTP_HOST ]]; then
|
||||
print "Host:\t\t$ZFTP_HOST"
|
||||
print "IP:\t\t$ZFTP_IP"
|
||||
[[ -n $ZFTP_SYSTEM ]] && print "System type:\t$ZFTP_SYSTEM"
|
||||
if [[ -n $ZFTP_USER ]]; then
|
||||
print "User:\t\t$ZFTP_USER "
|
||||
[[ -n $ZFTP_ACCOUNT ]] && print "Account:\t$AFTP_ACCOUNT"
|
||||
print "Directory:\t$ZFTP_PWD"
|
||||
print -n "Transfer type:\t"
|
||||
if [[ $ZFTP_TYPE = "I" ]]; then
|
||||
print Image
|
||||
elif [[ $ZFTP_TYPE = "A" ]]; then
|
||||
print Ascii
|
||||
else
|
||||
print Unknown
|
||||
fi
|
||||
print -n "Transfer mode:\t"
|
||||
if [[ $ZFTP_MODE = "S" ]]; then
|
||||
print Stream
|
||||
elif [[ $ZFTP_MODE = "B" ]]; then
|
||||
print Block
|
||||
else
|
||||
print Unknown
|
||||
fi
|
||||
else
|
||||
print "No user logged in."
|
||||
fi
|
||||
else
|
||||
print "Not connected."
|
||||
[[ -n $zflastsession ]] && print "Last session:\t$zflastsession"
|
||||
stat=1
|
||||
fi
|
||||
|
||||
# things which may be set even if not connected:
|
||||
[[ -n $ZFTP_REPLY ]] && print "Last reply:\t$ZFTP_REPLY"
|
||||
print "Verbosity:\t$ZFTP_VERBOSE"
|
||||
print "Timeout:\t$ZFTP_TMOUT"
|
||||
print -n "Preferences:\t"
|
||||
for (( i = 1; i <= ${#ZFTP_PREFS}; i++ )); do
|
||||
case $ZFTP_PREFS[$i] in
|
||||
[pP]) print -n "Passive "
|
||||
;;
|
||||
[sS]) print -n "Sendport "
|
||||
;;
|
||||
[dD]) print -n "Dumb "
|
||||
;;
|
||||
*) print -n "$ZFTP_PREFS[$i]???"
|
||||
esac
|
||||
done
|
||||
print
|
||||
|
||||
if [[ -n $ZFTP_HOST && $verbose = 1 ]]; then
|
||||
zfautocheck -d
|
||||
print "Status of remote server:"
|
||||
# make sure we print the reply
|
||||
local ZFTP_VERBOSE=045
|
||||
zftp quote STAT
|
||||
fi
|
||||
|
||||
return $stat
|
||||
# }
|
39
Functions/Zftp/zftp_chpwd
Normal file
39
Functions/Zftp/zftp_chpwd
Normal file
|
@ -0,0 +1,39 @@
|
|||
# function zftp_chpwd {
|
||||
# You may want to alter chpwd to call this when $ZFTP_USER is set.
|
||||
|
||||
# Cancel the filename cache for the current directory.
|
||||
zftp_fcache=()
|
||||
# ...and also empty the stored directory listing cache.
|
||||
# As this function is called when we close the connection, this
|
||||
# is the only place we need to do these two things.
|
||||
[[ -n $zfcurdir && -f $zfcurdir ]] && rm -f $zfcurdir
|
||||
zfotherargs=
|
||||
|
||||
if [[ -z $ZFTP_USER ]]; then
|
||||
# last call, after an FTP logout
|
||||
|
||||
# delete the non-current cached directory
|
||||
[[ -n $zfotherdir && -f $zfotherdir ]] && rm -f $zfotherdir
|
||||
|
||||
# don't keep zflastdir between opens (do keep zflastsession)
|
||||
zflastdir=
|
||||
|
||||
# return the display to standard
|
||||
# uncomment the following line if you have a chpwd which shows directories
|
||||
# chpwd
|
||||
else
|
||||
[[ -n $ZFTP_PWD ]] && zflastdir=$ZFTP_PWD
|
||||
zflastsession="$ZFTP_HOST:$ZFTP_PWD"
|
||||
local args
|
||||
if [[ -t 1 && -t 2 ]]; then
|
||||
local str=$zflastsession
|
||||
[[ ${#str} -lt 70 ]] && str="%m: %~ $str"
|
||||
case $TERM in
|
||||
sun-cmd) print -n -P "\033]l$str\033\\"
|
||||
;;
|
||||
xterm) print -n -P "\033]2;$str\a"
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
fi
|
||||
# }
|
18
Functions/Zftp/zftp_progress
Normal file
18
Functions/Zftp/zftp_progress
Normal file
|
@ -0,0 +1,18 @@
|
|||
# function zftp_progress {
|
||||
# Basic progress metre, showing the percent of the file transferred.
|
||||
# You want growing bars? You gotta write growing bars.
|
||||
|
||||
# Don't show progress unless stderr is a terminal
|
||||
[[ ! -t 2 ]] && return 0
|
||||
|
||||
if [[ $ZFTP_TRANSFER = *F ]]; then
|
||||
print 1>&2
|
||||
elif [[ -n $ZFTP_TRANSFER ]]; then
|
||||
if [[ -n $ZFTP_SIZE ]]; then
|
||||
local frac="$(( ZFTP_COUNT * 100 / ZFTP_SIZE ))%"
|
||||
print -n "\r$ZFTP_FILE ($ZFTP_SIZE bytes): $ZFTP_TRANSFER $frac" 1>&2
|
||||
else
|
||||
print -n "\r$ZFTP_FILE: $ZFTP_TRANSFER $ZFTP_COUNT" 1>&2
|
||||
fi
|
||||
fi
|
||||
# }
|
30
Functions/Zftp/zftype
Normal file
30
Functions/Zftp/zftype
Normal file
|
@ -0,0 +1,30 @@
|
|||
# function zftype {
|
||||
local type zftmp=${TMPPREFIX}zftype$$
|
||||
|
||||
zfautocheck -d
|
||||
|
||||
if (( $# == 0 )); then
|
||||
zftp type >$zftmp
|
||||
type=$(<$zftmp)
|
||||
rm -f $zftmp
|
||||
if [[ $type = I ]]; then
|
||||
print "Current type is image (binary)"
|
||||
return 0
|
||||
elif [[ $type = A ]]; then
|
||||
print "Current type is ASCII"
|
||||
return 0
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
else
|
||||
if [[ $1 == (#i)a(sc(ii|)|) ]]; then
|
||||
type=A
|
||||
elif [[ $1 == (#i)i(m(age|)|) || $1 == (#i)b(in(ary|)|) ]]; then
|
||||
type=I
|
||||
else
|
||||
print "Type not recognised: $1" 2>&1
|
||||
return 1
|
||||
fi
|
||||
zftp type $type
|
||||
fi
|
||||
# }
|
147
Functions/Zftp/zfuget
Normal file
147
Functions/Zftp/zfuget
Normal file
|
@ -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
|
||||
# }
|
115
Functions/Zftp/zfuput
Normal file
115
Functions/Zftp/zfuput
Normal file
|
@ -0,0 +1,115 @@
|
|||
# function zfuput {
|
||||
# Put a list of files from the server with update.
|
||||
# See zfuget for details.
|
||||
#
|
||||
# Options:
|
||||
# -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.
|
||||
|
||||
emulate -L zsh
|
||||
|
||||
local loc rem locstats remstats doit tmpfile=${TMPPREFIX}zfuput$$
|
||||
local rstat verbose optlist opt bad i silent
|
||||
integer stat do_close
|
||||
|
||||
zfuput_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
|
||||
}
|
||||
|
||||
zfuput_print () {
|
||||
print -n "\nremote $rem ("
|
||||
zfuput_print_time $remstats[2]
|
||||
print -n ", $remstats[1] bytes)\nlocal $loc ("
|
||||
zfuput_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
|
||||
;;
|
||||
*) print option $opt not recognised >&2
|
||||
;;
|
||||
esac
|
||||
done
|
||||
shift
|
||||
done
|
||||
|
||||
[[ -n $bad ]] && return 1
|
||||
|
||||
zfautocheck
|
||||
|
||||
if [[ $ZFTP_VERBOSE = *5* ]]; then
|
||||
# should we turn it off locally?
|
||||
print "Messages with code 550 are harmless." >&2
|
||||
fi
|
||||
|
||||
for rem in $*; do
|
||||
loc=${rem:t}
|
||||
doit=y
|
||||
remstats=()
|
||||
if [[ ! -f $loc ]]; then
|
||||
print "$loc: file not found" >&2
|
||||
stat=1
|
||||
continue
|
||||
fi
|
||||
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
|
||||
[[ $verbose = 1 ]] && print New file $loc
|
||||
else
|
||||
[[ $verbose = 1 ]] && zfuput_print
|
||||
if (( $locstats[1] != $remstats[1] )); then
|
||||
# Files have different sizes
|
||||
if [[ $locstats[2] < $remstats[2] && $silent != 1 ]]; then
|
||||
[[ $verbose != 1 ]] && zfuput_print
|
||||
print "Remote file $rem more recent than local," 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 ]] && zfuput_print
|
||||
print "Remote file $rem has same size as local," 1>&2
|
||||
print -n "but remote 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
|
||||
fi
|
||||
if [[ $doit = y ]]; then
|
||||
zftp put $rem <$loc || stat=$?
|
||||
fi
|
||||
done
|
||||
|
||||
(( do_close )) && zfclose
|
||||
|
||||
return $stat
|
||||
# }
|
Loading…
Reference in a new issue