sftpclient example python ssh sftp paramiko

example - Suba archivos usando SFTP en Python, pero cree directorios si la ruta no existe



sftp python (5)

Algo más simple y un poco más legible también

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

Quiero cargar un archivo en un servidor remoto con Python. Me gustaría comprobar de antemano si la ruta remota realmente existe, y si no es así, crearla. En pseudocódigo:

if(remote_path not exist): create_path(remote_path) upload_file(local_file, remote_path)

Estaba pensando en ejecutar un comando en Paramiko para crear la ruta (por ejemplo, mkdir -p remote_path ). Se me ocurrió esto:

# I didn''t test this code import paramiko, sys ssh = paramiko.SSHClient() ssh.connect(myhost, 22, myusername, mypassword) ssh.exec_command(''mkdir -p '' + remote_path) ssh.close transport = paramiko.Transport((myhost, 22)) transport.connect(username = myusername, password = mypassword) sftp = paramiko.SFTPClient.from_transport(transport) sftp.put(local_path, remote_path) sftp.close() transport.close()

Pero esta solución no me suena bien, porque cierro la conexión y la vuelvo a abrir. Hay una mejor manera de hacerlo?



SFTP es compatible con los comandos FTP habituales (chdir, mkdir, etc ...), así que usa esos:

sftp = paramiko.SFTPClient.from_transport(transport) try: sftp.chdir(remote_path) # Test if remote_path exists except 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 case sftp.close()

Para emular completamente mkdir -p , puedes trabajar a través de remote_path recursivamente:

import os.path def 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 True sftp = paramiko.SFTPClient.from_transport(transport) mkdir_p(sftp, remote_path) sftp.put(local_path, ''.'') # At this point, you are in remote_path sftp.close()

Por supuesto, si remote_path también contiene un nombre de archivo remoto, entonces debe dividirse, el directorio se pasa a mkdir_p y el nombre de archivo usado en lugar de ''.'' en sftp.put.


Suponiendo que las operaciones de sftp son caras, me gustaría ir con:

def sftp_mkdir_p(sftp, remote_directory): dirs_exist = remote_directory.split(''/'') dirs_make = [] # find level where dir doesn''t exist while len(dirs_exist) > 0: try: sftp.listdir(''/''.join(dirs_exist)) break except IOError: value = dirs_exist.pop() if value == '''': continue dirs_make.append(value) else: return False # ...and create dirs starting from that level for mdir in dirs_make[::-1]: dirs_exist.append(mdir) sftp.mkdir(''/''.join(dirs_exist))```


Tenía que hacer esto hoy. Así es como lo hice.

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)