Chapter 17 ■ Ftp
329
try:
ftp.cwd(dirpath)
except error_perm:
return # ignore non-directores and ones we cannot enter
print(dirpath)
names = sorted(ftp.nlst())
for name in names:
walk_dir(ftp, dirpath + '/' + name)
ftp.cwd(original_dir) # return to cwd of our caller
def main():
ftp = FTP('ftp.kernel.org')
ftp.login()
walk_dir(ftp, '/pub/linux/kernel/Historic/old-versions')
ftp.quit()
if name == 'main':
main()
This sample program will run a bit slow—there are, as it turns out, quite a few files in the old version’s directory
on the Linux kernel archive—but within a few dozen seconds, you should see the resulting directory tree displayed on
the screen:
$ python recursedl.py
/pub/linux/kernel/Historic/old-versions
/pub/linux/kernel/Historic/old-versions/impure
/pub/linux/kernel/Historic/old-versions/old
/pub/linux/kernel/Historic/old-versions/old/corrupt
/pub/linux/kernel/Historic/old-versions/tytso
By adding a few print statements, you could supplement this list of directories by displaying every one of the
files that the recursive process is (slowly) discovering. Moreover, by adding another few lines of code, you could
be downloading the files themselves to corresponding directories that you create locally. However, the only really
essential logic for a recursive download is already operating in the code in Listing 17-9: but the only foolproof way to
know if an entry is a directory that you are allowed to enter is to try running cwd() against it.
Creating Directories, Deleting Things
Finally, FTP supports file deletion, and it supports both the creation and deletion of directories. These more obscure
calls are all described in the ftplib documentation:
• delete(filename) will delete a file from the server.
• mkd(dirname) attempts to create a new directory.
• rmd(dirname) will delete a directory; note that most systems require the directory to be
empty first.