【问题标题】:How do I parse a listing of files to get just the filenames in Python?如何解析文件列表以仅获取 Python 中的文件名?
【发布时间】:2010-09-19 06:11:13
【问题描述】:

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

【问题讨论】:

    标签: python parsing scripting ftp ftplib


    【解决方案1】:

    我相信它应该适合你。

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

    【讨论】:

      【解决方案2】:

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

      【讨论】:

        【解决方案3】:

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

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

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

        【讨论】:

        • 如果文件名包含空格,这将不起作用(Mohit Ranka 的回答可能有同样的问题,但我无法完全理解他的代码......)
        【解决方案4】:

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

        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:])
        

        【讨论】:

        • 我认为这是一个非常有创意的技术,但是如果您列出顶级目录,那么列表中可能没有任何点文件。
        【解决方案5】:

        ftplib.FTP.nlst() 对你不起作用有什么原因吗?我刚刚检查过,它只返回给定目录中文件的名称。

        【讨论】:

        • 糟糕,好的。没注意到 James 已经建议了 nlst()?
        【解决方案6】:

        这个最佳答案

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

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

        系统管理员进程的生成器

        在他现在著名的评论Generator Tricks For Systems Programmers An Introduction 中,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)
        

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

        【讨论】:

        • 似乎比在我的情况下挂在空目录上的 nlst 更强大。
        【解决方案7】:

        如果FTP服务器支持MLSD命令,那么请看that答案中的“单目录案例”一节。

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

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

        【讨论】:

          猜你喜欢
          • 2017-04-23
          • 1970-01-01
          • 2018-04-05
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-02-24
          相关资源
          最近更新 更多