Crear directorios faltantes en ftplib storbinary

Estaba usando pycurl para transferir archivos a través de ftp en python. Podría crear los directorios faltantes automáticamente en mi servidor remoto usando:

c.setopt(pycurl.FTP_CREATE_MISSING_DIRS, 1) 

Por algunas razones, tengo que cambiar a ftplib. Pero no sé cómo hacer lo mismo aquí. ¿Hay alguna opción para agregar a la función storbinary para hacer eso? ¿O tengo que crear los directorios manualmente?

FTP_CREATE_MISSING_DIRS es una operación de curvatura ( agregada aquí ). Me atrevería a suponer que tiene que hacerlo manualmente con ftplib, pero me encantaría que se demuestre lo contrario, ¿alguien?

ftplib.all_errors algo como lo siguiente: (sin probar, y necesito capturar ftplib.all_errors )

 ftp = ... # Create connection # Change directories - create if it doesn't exist def chdir(dir): if directory_exists(dir) is False: # (or negate, whatever you prefer for readability) ftp.mkd(dir) ftp.cwd(dir) # Check if directory exists (in current location) def directory_exists(dir): filelist = [] ftp.retrlines('LIST',filelist.append) for f in filelist: if f.split()[-1] == dir and f.upper().startswith('D'): return True return False 

O podrías hacer directory_exists así: (un poco más difícil de leer?)

 # Check if directory exists (in current location) def directory_exists(dir): filelist = [] ftp.retrlines('LIST',filelist.append) return any(f.split()[-1] == dir and f.upper().startswith('D') for f in filelist) 

Sé que es una especie de publicación antigua, pero solo necesitaba esto y se me ocurrió una función muy simple. Soy nuevo en Python, así que agradecería cualquier comentario.

 from ftplib import FTP ftp = FTP('domain.com', 'username', 'password') def cdTree(currentDir): if currentDir != "": try: ftp.cwd(currentDir) except IOError: cdTree("/".join(currentDir.split("/")[:-1])) ftp.mkd(currentDir) ftp.cwd(currentDir) 

Ejemplo de uso:

 cdTree("/this/is/an/example") 

Intenté agregar esto como un comentario a la respuesta de @Alex L, pero fue demasiado largo. Es necesario descender recursivamente al cambiar de directorio si desea crear directorios en el camino. P.ej

 def chdir(ftp, directory): ch_dir_rec(ftp,directory.split('/')) # Check if directory exists (in current location) def directory_exists(ftp, directory): filelist = [] ftp.retrlines('LIST',filelist.append) for f in filelist: if f.split()[-1] == directory and f.upper().startswith('D'): return True return False def ch_dir_rec(ftp, descending_path_split): if len(descending_path_split) == 0: return next_level_directory = descending_path_split.pop(0) if not directory_exists(ftp,next_level_directory): ftp.mkd(next_level_directory) ftp.cwd(next_level_directory) ch_dir_rec(ftp,descending_path_split) 

Este código creará todas las carpetas faltantes en la ruta:

 ... def chdir(ftp_path, ftp_conn): dirs = [d for d in ftp_path.split('/') if d != ''] for p in dirs: print(p) check_dir(p, ftp_conn) def check_dir(dir, ftp_conn): filelist = [] ftp_conn.retrlines('LIST', filelist.append) found = False for f in filelist: if f.split()[-1] == dir and f.lower().startswith('d'): found = True if not found: ftp_conn.mkd(dir) ftp_conn.cwd(dir) if __name__ == '__main__': ftp_conn = ... # ftp connection t = 'FTP/for_Vadim/1/2/3/' chdir(t, ftp_conn) 

Este código verificará todos los directorios en la ruta y creará los directorios faltantes

antes de “FTP / for_Vadim /” después de “FTP / for_Vadim / 1/2/3 /”

Estoy usando algo como esto (sin cwd):

 # -*- coding:utf-8 -*- from ftplib import FTP, error_perm def createDirs(ftp, dirpath): """ Create dir with subdirs. :param ftp: connected FTP :param dirpath: path (like 'test/test1/test2') :type ftp: FTP :type dirpath: str :rtype: None """ dirpath = dirpath.replace('\\', '/') tmp = dirpath.split('/') dirs = [] for _ in tmp: if len(dirs) == 0: dirs.append(_) continue dirs.append(dirs[-1] + '/' + _) for _ in dirs: try: ftp.mkd(_) except error_perm as e: e_str = str(e) if '550' in e_str and 'File exists' in e_str: continue if __name__ == '__main__': # init ftp createDirs(ftp=ftp, dirpath='test/1/2/3')