Kaydet (Commit) fdc5adc5 authored tarafından Guido van Rossum's avatar Guido van Rossum

Dangerous feature added: when removing local files (i.e., only when -r

is used), do a recursive delete.  Use -r with even more caution!
Also changed usage message into a doc string, added a comment or two,
and rearranged a long line.
üst 85a5c527
#! /usr/bin/env python #! /usr/bin/env python
# Mirror a remote ftp subtree into a local directory tree. """Mirror a remote ftp subtree into a local directory tree.
# Basic usage: ftpmirror [options] host remotedir localdir
#
# XXX To do:
# - handle symbolic links
# - back up .mirrorinfo before overwriting
# - use pickles for .mirrorinfo?
import os
import sys
import time
import getopt
import string
import ftplib
from fnmatch import fnmatch
usage_msg = """
usage: ftpmirror [-v] [-q] [-i] [-m] [-n] [-r] [-s pat] usage: ftpmirror [-v] [-q] [-i] [-m] [-n] [-r] [-s pat]
[-l username [-p passwd [-a account]]] [-l username [-p passwd [-a account]]]
hostname [remotedir [localdir]] hostname [remotedir [localdir]]
...@@ -25,17 +10,31 @@ usage: ftpmirror [-v] [-q] [-i] [-m] [-n] [-r] [-s pat] ...@@ -25,17 +10,31 @@ usage: ftpmirror [-v] [-q] [-i] [-m] [-n] [-r] [-s pat]
-i: interactive mode -i: interactive mode
-m: macintosh server (NCSA telnet 2.4) (implies -n -s '*.o') -m: macintosh server (NCSA telnet 2.4) (implies -n -s '*.o')
-n: don't log in -n: don't log in
-r: remove files no longer pertinent -r: remove local files/directories no longer pertinent
-l username [-p passwd [-a account]]: login info (default anonymous ftp) -l username [-p passwd [-a account]]: login info (default anonymous ftp)
-s pat: skip files matching pattern -s pat: skip files matching pattern
hostname: remote host hostname: remote host
remotedir: remote directory (default initial) remotedir: remote directory (default initial)
localdir: local directory (default current) localdir: local directory (default current)
""" """
# XXX To do:
# - handle symbolic links
# - back up .mirrorinfo before overwriting
import os
import sys
import time
import getopt
import string
import ftplib
from fnmatch import fnmatch
# Print usage message and exit
def usage(*args): def usage(*args):
sys.stdout = sys.stderr sys.stdout = sys.stderr
for msg in args: print msg for msg in args: print msg
print usage_msg print __doc__
sys.exit(2) sys.exit(2)
verbose = 1 # 0 for -q, 2 for -v verbose = 1 # 0 for -q, 2 for -v
...@@ -45,6 +44,7 @@ rmok = 0 ...@@ -45,6 +44,7 @@ rmok = 0
nologin = 0 nologin = 0
skippats = ['.', '..', '.mirrorinfo'] skippats = ['.', '..', '.mirrorinfo']
# Main program: parse command line and start processing
def main(): def main():
global verbose, interactive, mac, rmok, nologin global verbose, interactive, mac, rmok, nologin
try: try:
...@@ -94,6 +94,7 @@ def main(): ...@@ -94,6 +94,7 @@ def main():
# #
mirrorsubdir(f, localdir) mirrorsubdir(f, localdir)
# Core logic: mirror one subdirectory (recursively)
def mirrorsubdir(f, localdir): def mirrorsubdir(f, localdir):
pwd = f.pwd() pwd = f.pwd()
if localdir and not os.path.isdir(localdir): if localdir and not os.path.isdir(localdir):
...@@ -137,7 +138,7 @@ def mirrorsubdir(f, localdir): ...@@ -137,7 +138,7 @@ def mirrorsubdir(f, localdir):
continue continue
if words[-2] == '->': if words[-2] == '->':
if verbose > 1: if verbose > 1:
print 'Skipping symbolic link %s -> %s' % \ print 'Skipping symbolic link %s -> %s' % \
(words[-3], words[-1]) (words[-3], words[-1])
continue continue
filename = words[-1] filename = words[-1]
...@@ -259,12 +260,8 @@ def mirrorsubdir(f, localdir): ...@@ -259,12 +260,8 @@ def mirrorsubdir(f, localdir):
print 'Local file', fullname, print 'Local file', fullname,
print 'is no longer pertinent' print 'is no longer pertinent'
continue continue
if verbose: print 'Removing local file', fullname if verbose: print 'Removing local file/dir', fullname
try: remove(fullname)
os.unlink(fullname)
except os.error, msg:
print "Can't remove local file %s: %s" % \
(fullname, str(msg))
# #
# Recursively mirror subdirectories # Recursively mirror subdirectories
for subdir in subdirs: for subdir in subdirs:
...@@ -294,6 +291,34 @@ def mirrorsubdir(f, localdir): ...@@ -294,6 +291,34 @@ def mirrorsubdir(f, localdir):
else: else:
if verbose > 1: print 'OK.' if verbose > 1: print 'OK.'
# Helper to remove a file or directory tree
def remove(fullname):
if os.path.isdir(fullname) and not os.path.islink(fullname):
try:
names = os.listdir(fullname)
except os.error:
names = []
ok = 1
for name in names:
if not remove(os.path.join(fullname, name)):
ok = 0
if not ok:
return 0
try:
os.rmdir(fullname)
except os.error, msg:
print "Can't remove local directory %s: %s" % \
(fullname, str(msg))
return 0
else:
try:
os.unlink(fullname)
except os.error, msg:
print "Can't remove local file %s: %s" % \
(fullname, str(msg))
return 0
return 1
# Wrapper around a file for writing to write a hash sign every block. # Wrapper around a file for writing to write a hash sign every block.
class LoggingFile: class LoggingFile:
def __init__(self, fp, blocksize, outfp): def __init__(self, fp, blocksize, outfp):
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment