Upload files using SFTP in Python, but create directories if path doesn't exist Upload files using SFTP in Python, but create directories if path doesn't exist python python

Upload files using SFTP in Python, but create directories if path doesn't exist


SFTP supports the usual FTP commands (chdir, mkdir, etc...), so use those:

sftp = paramiko.SFTPClient.from_transport(transport)try:    sftp.chdir(remote_path)  # Test if remote_path existsexcept IOError:    sftp.mkdir(remote_path)  # Create remote_path    sftp.chdir(remote_path)sftp.put(local_path, '.')    # At this point, you are in remote_path in either casesftp.close()

To fully emulate mkdir -p, you can work through remote_path recursively:

import os.pathdef mkdir_p(sftp, remote_directory):    """Change to this directory, recursively making new folders if needed.    Returns True if any folders were created."""    if remote_directory == '/':        # absolute path so change directory to root        sftp.chdir('/')        return    if remote_directory == '':        # top-level relative directory must exist        return    try:        sftp.chdir(remote_directory) # sub-directory exists    except IOError:        dirname, basename = os.path.split(remote_directory.rstrip('/'))        mkdir_p(sftp, dirname) # make parent directories        sftp.mkdir(basename) # sub-directory missing, so created it        sftp.chdir(basename)        return Truesftp = paramiko.SFTPClient.from_transport(transport)mkdir_p(sftp, remote_path) sftp.put(local_path, '.')    # At this point, you are in remote_pathsftp.close()

Of course, if remote_path also contains a remote file name, then it needs to be split off, the directory being passed to mkdir_p and the filename used instead of '.' in sftp.put.


Something simpler and slightly more readable too

def mkdir_p(sftp, remote, is_dir=False):    """    emulates mkdir_p if required.     sftp - is a valid sftp object    remote - remote path to create.     """    dirs_ = []    if is_dir:        dir_ = remote    else:        dir_, basename = os.path.split(remote)    while len(dir_) > 1:        dirs_.append(dir_)        dir_, _  = os.path.split(dir_)    if len(dir_) == 1 and not dir_.startswith("/"):         dirs_.append(dir_) # For a remote path like y/x.txt     while len(dirs_):        dir_ = dirs_.pop()        try:            sftp.stat(dir_)        except:            print "making ... dir",  dir_            sftp.mkdir(dir_)


Had to do this today. Here is how I did it.

def mkdir_p(sftp, remote_directory):    dir_path = str()    for dir_folder in remote_directory.split("/"):        if dir_folder == "":            continue        dir_path += r"/{0}".format(dir_folder)        try:            sftp.listdir(dir_path)        except IOError:            sftp.mkdir(dir_path)