Create missing directories in ftplib storbinary

后端 未结 6 868
傲寒
傲寒 2021-02-07 11:28

I was using pycurl to transfer files over ftp in python. I could create the missing directories automatically on my remote server using:

c.setopt(pycurl.FTP_CREA         


        
相关标签:
6条回答
  • 2021-02-07 11:47

    I'm using something like this (without 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')
    
    0 讨论(0)
  • 2021-02-07 11:48

    This code will create all missing folders in path:

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

    This code will check all dirs in path and create missing dirs

    before "FTP/for_Vadim/" after "FTP/for_Vadim/1/2/3/"

    0 讨论(0)
  • 2021-02-07 11:49

    I know it's kind of an old post but I just needed this and came up with a very simple function. I'm new to Python so I'd appreciate any feedback.

    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)
    

    Usage example:

    cdTree("/this/is/an/example")
    
    0 讨论(0)
  • 2021-02-07 11:54

    FTP_CREATE_MISSING_DIRS is a curl operation (added here). I'd hazard a guess that you have to do it manually with ftplib, but I'd love to be proven wrong, anyone?

    I'd do something like the following: (untested, and need to catch 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
    

    Or you could do directory_exists like this: (a bit harder to read?)

    # 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)
    
    0 讨论(0)
  • 2021-02-07 11:56

    I tried adding this as a comment to the @Alex L 's answer, but it was too long. You need to descend recursively when changing directory if you want to create directories on the way. E.g.

    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)
    
    0 讨论(0)
  • 2021-02-07 12:01

    I am using the following lines to resolve missing directory paths for FTP file copy

    import os
    ftps = FTP_TLS('ftps_server')
    ftps.connect()
    ftps.login()
    
    destination_dir_path = 'some/dir/path'          # directory path on FTP
    dir_path = ''
    for i in destination_dir_path.split('/'):
        dir_path = os.path.join(dir_path,i)
        if i not in ftps.nlst(os.path.dirname(dir_path)):
            ftps.mkd(dir_path)                      # create directory on the FTP
    ftps.storbinary(...)                            # store file using the binary mode
    
    0 讨论(0)
提交回复
热议问题