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()
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