Используя ftplib Python для получения списка каталогов, переносимо
-
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)