Directory transfers with Paramiko Directory transfers with Paramiko python python

Directory transfers with Paramiko


You can subclass paramiko.SFTPClient and add the following method to it:

import paramikoimport osclass MySFTPClient(paramiko.SFTPClient):    def put_dir(self, source, target):        ''' Uploads the contents of the source directory to the target path. The            target directory needs to exists. All subdirectories in source are             created under target.        '''        for item in os.listdir(source):            if os.path.isfile(os.path.join(source, item)):                self.put(os.path.join(source, item), '%s/%s' % (target, item))            else:                self.mkdir('%s/%s' % (target, item), ignore_existing=True)                self.put_dir(os.path.join(source, item), '%s/%s' % (target, item))    def mkdir(self, path, mode=511, ignore_existing=False):        ''' Augments mkdir by adding an option to not fail if the folder exists  '''        try:            super(MySFTPClient, self).mkdir(path, mode)        except IOError:            if ignore_existing:                pass            else:                raise

To use it:

transport = paramiko.Transport((HOST, PORT))transport.connect(username=USERNAME, password=PASSWORD)sftp = MySFTPClient.from_transport(transport)sftp.mkdir(target_path, ignore_existing=True)sftp.put_dir(source_path, target_path)sftp.close()


You'll need to do this just like you would locally with python (if you weren't using shutils).

Combine os.walk(), with sftp.mkdir() and sftp.put(). You may also want to check each file and directory with os.path.islink() depending on whether you want to resolve symlinks or not.


Here's my piece of code:

import errnoimport osimport statdef download_files(sftp_client, remote_dir, local_dir):    if not exists_remote(sftp_client, remote_dir):        return    if not os.path.exists(local_dir):        os.mkdir(local_dir)    for filename in sftp_client.listdir(remote_dir):        if stat.S_ISDIR(sftp_client.stat(remote_dir + filename).st_mode):            # uses '/' path delimiter for remote server            download_files(sftp_client, remote_dir + filename + '/', os.path.join(local_dir, filename))        else:            if not os.path.isfile(os.path.join(local_dir, filename)):                sftp_client.get(remote_dir + filename, os.path.join(local_dir, filename))def exists_remote(sftp_client, path):    try:        sftp_client.stat(path)    except IOError, e:        if e.errno == errno.ENOENT:            return False        raise    else:        return True