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

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

Вопрос

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

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

Решение

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

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

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

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

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

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

В своем ныне знаменитом обзоре Хитрости с генератором для системных программистов. Введение., Дэвид М.Бизли дает множество рецептов решения подобных проблем с данными с помощью кода многократного использования.

Э.Г:

# 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)

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

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

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

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

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

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

  

drwxrwsr-x 5 ftp-usr pdmaint 1536 марта 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:])

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

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

directory_filenames= [ftpfile.name for ftpfile in ftpd.files]

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

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

ЗАМЕЧАНИЯ -

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

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

  • '' .join (each_file.split ())

  • Чтобы заменить несколько пробелов на 1 пробел.

    Лицензировано под: CC-BY-SA с атрибуция
    Не связан с StackOverflow
    scroll top