Проверка, является ли объект на FTP-сервере файлом или каталогом, используя Python и ftplib

Используя Python и ftplib, я пишу универсальную функцию, чтобы проверить, являются ли элементы в каталоге FTP файлами или каталогами. Поскольку использование функции MLSD может не обязательно работать со всеми серверами (один из моих вариантов использования не предусматривает этого), я прибегнул к этому эффективному, но грубому способу определения, пытаясь изменить каталог на объект, и если объект файл, возникает исключение, и тип файла устанавливается соответственно.

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

Я просмотрел документацию по Интернету и библиотеке для других методов, но я не могу найти те, которые будут работать в большинстве случаев.

Например, используя dir функция, я могу проверить, если первый символ 'd' и это может определить это, однако дальнейшее чтение показало, что не все выходные данные имеют одинаковый формат.

Самый большой недостаток, который я вижу в этом методе, это то, что у меня нет разрешения сменить каталог на указанную папку; следовательно, он будет рассматриваться как файл.

Есть ли что-то, что я пропускаю или более чистый способ сделать это?

2 ответа

Решение

Нет лучшего способа (с протоколом FTP в целом, а не только с ftplib).

MLST/MLSD это единственный правильный и надежный способ.

Если вы не можете использовать MLST/MLSD, пытаясь CWD это следующий лучший вариант.

Пытаюсь разобрать LIST это запасной вариант. Но вы должны знать, что сервер использует формат листинга, который понимает ваша программа.

Вот функция, которую я использовал через FTP-версию os.walk для FTP серверов. Вот ссылка на github, если вы хотите увидеть полный код 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

Объяснение:

Здесь все, что вам нужно, это циклически перемещаться по файлам и каталогам в пределах вашего предполагаемого каталога и выбирать каталоги. Но так как вы не можете сделать это так, как вы используете в ОС, вам нужно использовать ftplib.FTP.retrlines() функция, которая извлекает список файлов или каталогов в режиме передачи ASCII, затем вы можете разделить каталоги, анализируя эти строки.

Другие вопросы по тегам