Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit fdc5adc

Browse files
committed
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.
1 parent 85a5c52 commit fdc5adc

1 file changed

Lines changed: 50 additions & 25 deletions

File tree

Tools/scripts/ftpmirror.py

Lines changed: 50 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,7 @@
11
#! /usr/bin/env python
22

3-
# Mirror a remote ftp subtree into a local directory tree.
4-
# Basic usage: ftpmirror [options] host remotedir localdir
5-
#
6-
# XXX To do:
7-
# - handle symbolic links
8-
# - back up .mirrorinfo before overwriting
9-
# - use pickles for .mirrorinfo?
10-
11-
import os
12-
import sys
13-
import time
14-
import getopt
15-
import string
16-
import ftplib
17-
from fnmatch import fnmatch
3+
"""Mirror a remote ftp subtree into a local directory tree.
184
19-
usage_msg = """
205
usage: ftpmirror [-v] [-q] [-i] [-m] [-n] [-r] [-s pat]
216
[-l username [-p passwd [-a account]]]
227
hostname [remotedir [localdir]]
@@ -25,17 +10,31 @@
2510
-i: interactive mode
2611
-m: macintosh server (NCSA telnet 2.4) (implies -n -s '*.o')
2712
-n: don't log in
28-
-r: remove files no longer pertinent
13+
-r: remove local files/directories no longer pertinent
2914
-l username [-p passwd [-a account]]: login info (default anonymous ftp)
3015
-s pat: skip files matching pattern
3116
hostname: remote host
3217
remotedir: remote directory (default initial)
3318
localdir: local directory (default current)
3419
"""
20+
21+
# XXX To do:
22+
# - handle symbolic links
23+
# - back up .mirrorinfo before overwriting
24+
25+
import os
26+
import sys
27+
import time
28+
import getopt
29+
import string
30+
import ftplib
31+
from fnmatch import fnmatch
32+
33+
# Print usage message and exit
3534
def usage(*args):
3635
sys.stdout = sys.stderr
3736
for msg in args: print msg
38-
print usage_msg
37+
print __doc__
3938
sys.exit(2)
4039

4140
verbose = 1 # 0 for -q, 2 for -v
@@ -45,6 +44,7 @@ def usage(*args):
4544
nologin = 0
4645
skippats = ['.', '..', '.mirrorinfo']
4746

47+
# Main program: parse command line and start processing
4848
def main():
4949
global verbose, interactive, mac, rmok, nologin
5050
try:
@@ -94,6 +94,7 @@ def main():
9494
#
9595
mirrorsubdir(f, localdir)
9696

97+
# Core logic: mirror one subdirectory (recursively)
9798
def mirrorsubdir(f, localdir):
9899
pwd = f.pwd()
99100
if localdir and not os.path.isdir(localdir):
@@ -137,7 +138,7 @@ def mirrorsubdir(f, localdir):
137138
continue
138139
if words[-2] == '->':
139140
if verbose > 1:
140-
print 'Skipping symbolic link %s -> %s' % \
141+
print 'Skipping symbolic link %s -> %s' % \
141142
(words[-3], words[-1])
142143
continue
143144
filename = words[-1]
@@ -259,12 +260,8 @@ def mirrorsubdir(f, localdir):
259260
print 'Local file', fullname,
260261
print 'is no longer pertinent'
261262
continue
262-
if verbose: print 'Removing local file', fullname
263-
try:
264-
os.unlink(fullname)
265-
except os.error, msg:
266-
print "Can't remove local file %s: %s" % \
267-
(fullname, str(msg))
263+
if verbose: print 'Removing local file/dir', fullname
264+
remove(fullname)
268265
#
269266
# Recursively mirror subdirectories
270267
for subdir in subdirs:
@@ -294,6 +291,34 @@ def mirrorsubdir(f, localdir):
294291
else:
295292
if verbose > 1: print 'OK.'
296293

294+
# Helper to remove a file or directory tree
295+
def remove(fullname):
296+
if os.path.isdir(fullname) and not os.path.islink(fullname):
297+
try:
298+
names = os.listdir(fullname)
299+
except os.error:
300+
names = []
301+
ok = 1
302+
for name in names:
303+
if not remove(os.path.join(fullname, name)):
304+
ok = 0
305+
if not ok:
306+
return 0
307+
try:
308+
os.rmdir(fullname)
309+
except os.error, msg:
310+
print "Can't remove local directory %s: %s" % \
311+
(fullname, str(msg))
312+
return 0
313+
else:
314+
try:
315+
os.unlink(fullname)
316+
except os.error, msg:
317+
print "Can't remove local file %s: %s" % \
318+
(fullname, str(msg))
319+
return 0
320+
return 1
321+
297322
# Wrapper around a file for writing to write a hash sign every block.
298323
class LoggingFile:
299324
def __init__(self, fp, blocksize, outfp):

0 commit comments

Comments
 (0)