Downloading a directory tree with ftplib Downloading a directory tree with ftplib python python

Downloading a directory tree with ftplib


this should do the trick :)

import sysimport ftplibimport osfrom ftplib import FTPftp=FTP("ftp address")ftp.login("user","password")def downloadFiles(path,destination):#path & destination are str of the form "/dir/folder/something/"#path should be the abs path to the root FOLDER of the file tree to download    try:        ftp.cwd(path)        #clone path to destination        os.chdir(destination)        os.mkdir(destination[0:len(destination)-1]+path)        print destination[0:len(destination)-1]+path+" built"    except OSError:        #folder already exists at destination        pass    except ftplib.error_perm:        #invalid entry (ensure input form: "/dir/folder/something/")        print "error: could not change to "+path        sys.exit("ending session")    #list children:    filelist=ftp.nlst()    for file in filelist:        try:            #this will check if file is folder:            ftp.cwd(path+file+"/")            #if so, explore it:            downloadFiles(path+file+"/",destination)        except ftplib.error_perm:            #not a folder with accessible content            #download & return            os.chdir(destination[0:len(destination)-1]+path)            #possibly need a permission exception catch:            ftp.retrbinary("RETR "+file, open(os.path.join(destination,file),"wb").write)            print file + " downloaded"    returnsource="/ftproot/folder_i_want/"dest="/systemroot/where_i_want_it/"downloadFiles(source,dest)


This is a very old question, but I had a similar need that i wanted to satisfy in a very general manner. I ended up writing my own solution that works very well for me. I've placed it on Gist here https://gist.github.com/Jwely/ad8eb800bacef9e34dd775f9b3aad987

and pasted it below in case i ever take the gist offline.

Example usage:

import ftplibftp = ftplib.FTP(mysite, username, password)download_ftp_tree(ftp, remote_dir, local_dir)

The code above will look for a directory called "remote_dir" on the ftp host, and then duplicate the directory and its entire contents into the "local_dir".It invokes the script below.

import ftplibimport osdef _is_ftp_dir(ftp_handle, name, guess_by_extension=True):    """ simply determines if an item listed on the ftp server is a valid directory or not """    # if the name has a "." in the fourth to last position, its probably a file extension    # this is MUCH faster than trying to set every file to a working directory, and will work 99% of time.    if guess_by_extension is True:        if name[-4] == '.':            return False    original_cwd = ftp_handle.pwd()     # remember the current working directory    try:        ftp_handle.cwd(name)            # try to set directory to new name        ftp_handle.cwd(original_cwd)    # set it back to what it was        return True    except:        return Falsedef _make_parent_dir(fpath):    """ ensures the parent directory of a filepath exists """    dirname = os.path.dirname(fpath)    while not os.path.exists(dirname):        try:            os.mkdir(dirname)            print("created {0}".format(dirname))        except:            _make_parent_dir(dirname)def _download_ftp_file(ftp_handle, name, dest, overwrite):    """ downloads a single file from an ftp server """    _make_parent_dir(dest)    if not os.path.exists(dest) or overwrite is True:        with open(dest, 'wb') as f:            ftp_handle.retrbinary("RETR {0}".format(name), f.write)        print("downloaded: {0}".format(dest))    else:        print("already exists: {0}".format(dest))def _mirror_ftp_dir(ftp_handle, name, overwrite, guess_by_extension):    """ replicates a directory on an ftp server recursively """    for item in ftp_handle.nlst(name):        if _is_ftp_dir(ftp_handle, item):            _mirror_ftp_dir(ftp_handle, item, overwrite, guess_by_extension)        else:            _download_ftp_file(ftp_handle, item, item, overwrite)def download_ftp_tree(ftp_handle, path, destination, overwrite=False, guess_by_extension=True):    """    Downloads an entire directory tree from an ftp server to the local destination    :param ftp_handle: an authenticated ftplib.FTP instance    :param path: the folder on the ftp server to download    :param destination: the local directory to store the copied folder    :param overwrite: set to True to force re-download of all files, even if they appear to exist already    :param guess_by_extension: It takes a while to explicitly check if every item is a directory or a file.        if this flag is set to True, it will assume any file ending with a three character extension ".???" is        a file and not a directory. Set to False if some folders may have a "." in their names -4th position.    """    os.chdir(destination)    _mirror_ftp_dir(ftp_handle, path, overwrite, guess_by_extension)


this is an alternative. you can try using ftputil package. You can then use it to walk the remote directories and get your files