Checking if object on FTP server is file or directory using Python and ftplib
Asked Answered
O

2

2

Using Python and ftplib, I'm writing a generic function to check whether the items in an FTP directory are either files or directories. Since using the MLSD function might not necessarily work with all servers ( one of my use cases does not provide for it ) I have resorted to this effective but crude manner of determining it, by attempting to change directory to the object and if the object is a file, an exception is raised and the file type is set accordingly.

file_type = ''
try:
    ftp.cwd(item_name)
    file_type = 'dir'
    ftp.cwd(cur_path)
except ftplib.error_perm:
    file_type = 'file'

I have scoured the internet and library documentation for other methods, but I cannot find ones that would work on most cases.

For example using the dir function, I can check if the first character is 'd' and this might determine it, however further reading has indicated that not all output is of the same format.

The biggest flaw I can see in this method is if I do not have permission to change directory to the specified folder; hence it will be treated as a file.

Is there something I am missing or a cleaner way to do this?

Oceanus answered 27/4, 2016 at 15:59 Comment(0)
N
1

There's no better way (with FTP protocol in general, not just with ftplib).

The MLST/MLSD is the only correct and reliable way.

If you cannot use MLST/MLSD, trying CWD is the next best option.

Trying to parse LIST is a fallback option. But you need to know that the server uses listing format your program understands.

Negrito answered 27/4, 2016 at 16:32 Comment(0)
W
0

Here is a function that I've used through the FTP version of os.walk for FTP servers. Here is the github link if you want to see the full code https://github.com/Kasramvd/FTPwalk:

def listdir(self, connection, _path):
    file_list, dirs, nondirs = [], [], []
    try:
        connection.cwd(_path)
    except:
        return [], []

    connection.retrlines('LIST', lambda x: file_list.append(x.split()))
    for info in file_list:
        ls_type, name = info[0], info[-1]
        if ls_type.startswith('d'):
            dirs.append(name)
        else:
            nondirs.append(name)
    return dirs, nondirs

Explanation:

Here, all you need is looping over the files and directories within your intended directory and pick the directories. But since you can not do that like the way you use in OS, you need to use ftplib.FTP.retrlines() function that retrieves a file or directory listing in ASCII transfer mode then you can separate the directories by parsing these lines.

Woodwind answered 27/4, 2016 at 16:33 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.