5

因此,假设我正在使用 Python 的ftplib从 FTP 服务器检索日志文件列表。我将如何解析该文件列表以仅获取列表中的文件名(最后一列)?有关示例输出,请参见上面的链接。

4

7 回答 7

9

使用 retrlines() 可能不是最好的主意,因为它只是打印到控制台,所以你必须做一些棘手的事情才能得到那个输出。一个可能更好的选择是使用 nlst() 方法,它准确地返回你想要的:文件名列表。

于 2008-10-26T07:55:46.700 回答
8

这个最佳答案

您可能想要使用ftp.nlst()而不是ftp.retrlines(). 它会给你你想要的。

如果不能,请阅读以下内容:

系统管理员进程的生成器

在他现在著名的评论,系统程序员的生成器技巧简介中,David M. Beazley 给出了很多答案,用 wuick 和可重用的代码来回答这种数据问题。

例如:

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

好的,这在这里可能并不明显,但是对于大型批处理脚本来说,这很好:-)

于 2008-10-26T09:09:11.963 回答
1

顺便说一下,如果您由于某种原因无法使用 retrlines() ,那么一种稍微不太理想的方法是将函数作为第二个参数传递给 retrlines(); 它将为列表中的每个项目调用。所以像这样的东西(假设你有一个名为'ftp'的FTP对象)也可以工作:

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

列表“文件名”将是文件名列表。

于 2008-10-26T07:59:52.260 回答
1

由于输出中的每个文件名都从同一列开始,因此您所要做的就是获取第一行上点的位置:

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:])
于 2008-10-26T08:00:33.320 回答
1

ftplib.FTP.nlst()有什么理由不适合你吗?我刚刚检查过,它只返回给定目录中文件的名称。

于 2008-10-26T08:15:24.273 回答
1

如果 FTP 服务器支持该MLSD命令,请参阅答案中的“单目录案例”部分。

使用该类的一个实例(例如ftpd),在正确的文件夹中使用连接的实例FTPDirectory调用其方法,然后您可以:.getdataftplib.FTP

directory_filenames= [ftpfile.name for ftpfile in ftpd.files]
于 2010-06-24T23:17:14.247 回答
0

我相信它应该对你有用。

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 个空格替换多个空格。

于 2008-10-26T07:52:53.787 回答