Использование ftplib Python для получения списка каталогов, переносимо

Вы можете использовать ftplib для полной поддержки FTP в Python. Однако предпочтительный способ получить список каталогов:

# File: ftplib-example-1.py

import ftplib

ftp = ftplib.FTP("www.python.org")
ftp.login("anonymous", "ftplib-example-1")

data = []

ftp.dir(data.append)

ftp.quit()

for line in data:
    print "-", line

Который дает:

$ python ftplib-example-1.py
- total 34
- drwxrwxr-x  11 root     4127         512 Sep 14 14:18 .
- drwxrwxr-x  11 root     4127         512 Sep 14 14:18 ..
- drwxrwxr-x   2 root     4127         512 Sep 13 15:18 RCS
- lrwxrwxrwx   1 root     bin           11 Jun 29 14:34 README -> welcome.msg
- drwxr-xr-x   3 root     wheel        512 May 19  1998 bin
- drwxr-sr-x   3 root     1400         512 Jun  9  1997 dev
- drwxrwxr--   2 root     4127         512 Feb  8  1998 dup
- drwxr-xr-x   3 root     wheel        512 May 19  1998 etc
...

Думаю, идея состоит в том, чтобы проанализировать результаты, чтобы получить список каталогов. Однако этот список напрямую зависит от способа форматирования списка FTP-сервером. Было бы очень запутанно писать для этого код, предвидя все возможные способы форматирования этого списка FTP-серверами.

Есть ли переносимый способ заполнить массив списком каталогов?

(В массиве должны быть только имена папок.)

Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
64
0
112 310
7
Перейти к ответу Данный вопрос помечен как решенный

Ответы 7

Ответ принят как подходящий

Попробуйте использовать ftp.nlst(dir).

Однако обратите внимание, что если папка пуста, может возникнуть ошибка:

files = []

try:
    files = ftp.nlst()
except ftplib.error_perm, resp:
    if str(resp) == "550 No files found":
        print "No files in this directory"
    else:
        raise

for f in files:
    print f

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

Chris Hayes 01.07.2011 11:20

Спасибо за это. 5 лет спустя: устарело, начиная с версии 3.3: вместо этого используйте mlsd ().

tommy.carstensen 22.05.2013 13:42

Даже сегодня многие ftp-серверы не поддерживают команду MLSD.

cfi 16.01.2019 13:32

Стандартного формата ответа LIST нет. Вам нужно будет написать код для обработки наиболее популярных макетов. Я бы начал с форматов Linux ls и Windows Server DIR. Тем не менее, есть много разнообразия.

Вернитесь к методу nlst (возвращающему результат команды NLST), если вы не можете проанализировать более длинный список. Для бонусных баллов используйте чит: возможно, самое длинное число в строке, содержащей известное имя файла, - это его длина.

Никогда не предполагайте этого. Гадание всегда приводит к неизвестным ошибкам, когда вы меньше всего их ожидаете

iElectric 26.08.2010 22:50

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

Garth Kidd 01.09.2010 09:00

Надежный / стандартизированный способ анализа списка каталогов FTP - использование команды MLSD, которая к настоящему времени должна поддерживаться всеми недавними / достойными FTP-серверами.

import ftplib
f = ftplib.FTP()
f.connect("localhost")
f.login()
ls = []
f.retrlines('MLSD', ls.append)
for entry in ls:
    print entry

Приведенный выше код напечатает:

modify=20110723201710;perm=el;size=4096;type=dir;unique=807g4e5a5; tests
modify=20111206092323;perm=el;size=4096;type=dir;unique=807g1008e0; .xchat2
modify=20111022125631;perm=el;size=4096;type=dir;unique=807g10001a; .gconfd
modify=20110808185618;perm=el;size=4096;type=dir;unique=807g160f9a; .skychart
...

Начиная с python 3.3 ftplib предоставляет для этого специальный метод:

Я застрял на FTP-сервере (виртуальном сервере Rackspace Cloud Sites), который, похоже, не поддерживает MLSD. Тем не менее, мне нужно несколько полей информации о файле, таких как размер и временная метка, а не только имя файла, поэтому я должен использовать команду DIR. На этом сервере вывод DIR очень похож на OP. На случай, если это кому-то поможет, вот небольшой класс Python, который анализирует строку такого вывода, чтобы получить имя файла, размер и временную метку.

дата и время импорта

class FtpDir:
    def parse_dir_line(self, line):
        words = line.split()
        self.filename = words[8]
        self.size = int(words[4])
        t = words[7].split(':')
        ts = words[5] + '-' + words[6] + '-' + datetime.datetime.now().strftime('%Y') + ' ' + t[0] + ':' + t[1]
        self.timestamp = datetime.datetime.strptime(ts, '%b-%d-%Y %H:%M')

Я знаю, что она не очень портативна, но ее легко расширить или изменить для работы с различными FTP-серверами.

Это из документов Python

>>> from ftplib import FTP_TLS
>>> ftps = FTP_TLS('ftp.python.org')
>>> ftps.login()           # login anonymously before securing control 
channel
>>> ftps.prot_p()          # switch to secure data connection
>>> ftps.retrlines('LIST') # list directory content securely
total 9
drwxr-xr-x   8 root     wheel        1024 Jan  3  1994 .
drwxr-xr-x   8 root     wheel        1024 Jan  3  1994 ..
drwxr-xr-x   2 root     wheel        1024 Jan  3  1994 bin
drwxr-xr-x   2 root     wheel        1024 Jan  3  1994 etc
d-wxrwxr-x   2 ftp      wheel        1024 Sep  5 13:43 incoming
drwxr-xr-x   2 root     wheel        1024 Nov 17  1993 lib
drwxr-xr-x   6 1094     wheel        1024 Sep 13 19:07 pub
drwxr-xr-x   3 root     wheel        1024 Jan  3  1994 usr
-rw-r--r--   1 root     root          312 Aug  1  1994 welcome.msg

Это помогло мне с моим кодом.

Когда я пробовал использовать только тип файлов и отображать их на экране, добавляя условие, которое проверяет каждую строку.

Так

elif command == 'ls':
    print("directory of ", ftp.pwd())
    data = []
    ftp.dir(data.append)

    for line in data:
        x = line.split(".")
        formats=["gz", "zip", "rar", "tar", "bz2", "xz"]
        if x[-1] in formats:
            print ("-", line)

Я нашел свой путь сюда, пытаясь получить имена файлов, последние измененные штампы, размеры файлов и т. д., И хотел добавить свой код. Потребовалось всего несколько минут, чтобы написать цикл для анализа ftp.dir(dir_list.append) с использованием таких файлов Python std lib, как strip() (для очистки строки текста) и split() для создания массива.

ftp = FTP('sick.domain.bro')
ftp.login()
ftp.cwd('path/to/data')

dir_list = []
ftp.dir(dir_list.append)

# main thing is identifing which char marks start of good stuff
# '-rw-r--r--   1 ppsrt    ppsrt      545498 Jul 23 12:07 FILENAME.FOO
#                               ^  (that is line[29])

for line in dir_list:
   print line[29:].strip().split(' ') # got yerself an array there bud!
   # EX ['545498', 'Jul', '23', '12:07', 'FILENAME.FOO']

Мне это нравится. Очень чистый. Я просто использовал «строку печати», и мне этого было достаточно.

Zonker.in.Geneva 14.06.2019 14:49

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