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

StackOverflow https://stackoverflow.com/questions/111954

  •  02-07-2019
  •  | 
  •  

Вопрос

Вы можете использовать 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-серверами.

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

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

Это было полезно?

Решение

Попробуйте использовать 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

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

Надежный / стандартизированный способ анализа списка каталогов 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.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']

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

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

Так получилось, что я застрял с FTP-сервером (виртуальный сервер облачных сайтов Rackspace), который, похоже, не поддерживает 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)
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top