Как мне разобрать список файлов, чтобы получить только имена файлов в Python? - PullRequest
3 голосов
/ 26 октября 2008

Допустим, я использую Python ftplib для получения списка файлов журнала с FTP-сервера. Как бы я проанализировал этот список файлов, чтобы получить только имена файлов (последний столбец) внутри списка? См. Ссылку выше для примера вывода.

Ответы [ 7 ]

9 голосов
/ 26 октября 2008

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

6 голосов
/ 26 октября 2008

Это лучший ответ

Возможно, вы захотите использовать ftp.nlst() вместо ftp.retrlines(). Это даст вам именно то, что вы хотите.

Если вы не можете, прочитайте следующее:

Генераторы для процессов sysadmin

В своем теперь известном обзоре, Советы по созданию генератора для системных программистов. Введение , Дэвид М. Бизли (David M. Beazley) дает множество рецептов, чтобы ответить на такую ​​проблему с данными в коде wuick и многоразового использования.

E.G:

# empty list that will receive all the log entry
log = [] 
# we pass a callback function bypass the print_line that would be called by retrlines
# we do that only because we cannot use something better than retrlines
ftp.retrlines('LIST', callback=log.append)
# we use rsplit because it more efficient in our case if we have a big file
files = (line.rsplit(None, 1)[1] for line in log)
# get you file list
files_list = list(files)

Почему бы нам сразу не создать список?

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

РЕДАКТИРОВАТЬ: хорошо, я прочитал комментарий к другому ответу, и он говорит, что это не будет работать, если в имени есть пробел.

Круто, это проиллюстрирует, почему этот метод удобен. Если вы хотите что-то изменить в процессе, вы просто измените строку. Обмен:

files = (line.rsplit(None, 1)[1] for line in log)

и

# join split the line, get all the item from the field 8 then join them
files = (' '.join(line.split()[8:]) for line in log)

Хорошо, здесь это может быть неочевидно, но для сценариев с большими пакетными процессами это хорошо: -)

1 голос
/ 25 июня 2010

Если FTP-сервер поддерживает команду MLSD, см. Раздел «регистр одного каталога» из , который отвечает.

Используйте экземпляр (скажем, ftpd) класса FTPDirectory, вызовите его метод .getdata с подключенным экземпляром ftplib.FTP в правильной папке, затем вы можете:

directory_filenames= [ftpfile.name for ftpfile in ftpd.files]
1 голос
/ 26 октября 2008

Есть ли причина, по которой ftplib.FTP.nlst () не будет работать для вас? Я только что проверил, и он возвращает только имена файлов в данном каталоге.

1 голос
/ 26 октября 2008

Поскольку каждое имя файла в выводе начинается с одного и того же столбца, все, что вам нужно сделать, это получить положение точки в первой строке:

drwxrwsr-x 5 ftp-usr pdmaint 1536 Mar 20 09:48 .

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

Поскольку точка является последним символом в строке, вы можете использовать длину строки минус 1 в качестве индекса. Итак, окончательный код выглядит примерно так:

lines = ftp.retrlines('LIST')
lines = lines.split("\n") # This should split the string into an array of lines

filename_index = len(lines[0]) - 1
files = []

for line in lines:
    files.append(line[filename_index:])
1 голос
/ 26 октября 2008

И, кстати, чуть менее оптимальный метод, если по какой-то причине вы застряли с использованием retrlines (), это передать функцию в качестве второго аргумента в retrlines (); он будет вызываться для каждого элемента в списке. Поэтому что-то вроде этого (при условии, что у вас есть FTP-объект с именем 'ftp') также будет работать:

filenames = []
ftp.retrlines('LIST', lambda line: filenames.append(line.split()[-1]))

Список имен файлов будет тогда списком имен файлов.

0 голосов
/ 26 октября 2008

Я считаю, что это должно работать для вас.

file_name_list = [' '.join(each_file.split()).split()[-1] for each_file_detail in file_list_from_log]

ПРИМЕЧАНИЯ -

  1. Здесь я предполагаю, что вам нужны данные в программе (в виде списка), а не на консоли.

  2. each_file_detail - это каждая строка, создаваемая программой.

  3. '' .join (each_file.split ())

Для замены нескольких пробелов на 1 пробел.

...