【问题标题】:os.listdir analog for a zipped directoryos.listdir 模拟压缩目录
【发布时间】:2016-06-20 14:24:28
【问题描述】:

我的目标是列出某个 sub 压缩包内的某个目录中包含的所有文件。

os.listdir(target_dir) 引发FileNotFoundError,而zfile.namelist() 仅列出所有目录中的所有文件。

有什么想法吗?

【问题讨论】:

    标签: python python-2.7 python-3.x zipfile


    【解决方案1】:

    尝试以下方法:

    files = list(filter(lambda f: f.startswith("subdir"), zfile.namelist()))
    
    print(files)
    

    解释:filter 在检查文件名是否以“subdir”开头的lambda 上过滤zfile.namelist() 提供的列表。

    filter 函数不返回列表,而是返回过滤器对象(生成器),因此我们需要将其转换为列表。

    您也可以使用以下行,它执行相同但使用列表理解:

    files = [f for f in zfile.namelist() if f.startswith("subdir")]
    

    编辑:正如advance512 指出的那样:“这个解决方案的问题是它还会返回您正在检查的子目录内的子目录中的文件。”:

    files = [f for f in zfile.namelist() if f.startswith("subdir") and f.count("/") == 1]
    

    这不会返回子目录中的任何文件。

    【讨论】:

    • 这个解决方案的问题是它还会返回您正在检查的子目录内的子目录中的文件。如果这是您正在寻找的,那么这是一个很好的解决方案(我通常也更喜欢 lambda 和理解,但您要求的是一个函数)。
    • @advance512 谢谢,我没有考虑过。我更新了我的答案。
    • 或者您可以使用正则表达式来获取特定子目录的所有文件(≠子目录):files = [f for f in zipfile.namelist() if re.compile("^(" + re.escape("subdir") + r"\/[^\/]*?)$").match(f)]。但在这种情况下,您必须导入并使用 re 模块。因此,我更喜欢@SimonKirsten 原始答案。
    • 另外,在@Darius 代码示例中,您会为每个文件名编译一次正则表达式...性能不佳。如果有的话,在理解之外编译正则表达式。在这种情况下,正则表达式似乎有点矫枉过正。
    【解决方案2】:

    您可以使用提供的 zip_listdir 函数,该函数有点快-n-dirty,但应该始终可以在 Unix 克隆中使用。

    class MockZipFile(object):
        fake_file_names = [
            "string.pyc",  # Top level name
            "test/__init__.pyc",  # Package directory
            "test/test_support.pyc",  # Module test.test_support
            "test/bogus/__init__.pyc",  # Subpackage directory
            "test/bogus/myfile.pyc"  # Submodule test.bogus.myfile
        ]
    
        def namelist(self):
            return self.fake_file_names
    
    
    def zip_listdir(zip_file, target_dir):
    
        file_names = zip_file.namelist()
    
        if not target_dir.endswith("/"):
            target_dir += "/"
    
        if target_dir == "/":
            target_dir = ""
    
        result = [ file_name
                   for file_name in file_names
                   if file_name.startswith(target_dir) and
                      not "/" in file_name[len(target_dir):]
                   ]
    
        return result
    
    mockZipfile = MockZipFile()
    print zip_listdir(zip_file=mockZipfile, target_dir="test")
    print zip_listdir(zip_file=mockZipfile, target_dir="test/bogus")
    print zip_listdir(zip_file=mockZipfile, target_dir="test/")
    print zip_listdir(zip_file=mockZipfile, target_dir="/")
    print zip_listdir(zip_file=mockZipfile, target_dir="")
    print zip_listdir(zip_file=mockZipfile, target_dir="/asd")
    

    请注意,我创建了一个 MockZipFile 类,并将其用作zip_listdir 函数的输入,但正确的zipfile 对象应该完全相同。

    【讨论】:

      猜你喜欢
      • 2018-12-10
      • 2016-04-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-12-09
      • 2022-06-17
      • 1970-01-01
      相关资源
      最近更新 更多