【问题标题】:Unzip all zipped files in a folder to that same folder using Python 2.7.5使用 Python 2.7.5 将文件夹中的所有压缩文件解压缩到同一文件夹
【发布时间】:2015-09-29 13:23:57
【问题描述】:

我想编写一个简单的脚本来遍历文件夹中的所有文件,并将那些已压缩 (.zip) 的文件解压缩到同一个文件夹。对于这个项目,我有一个包含近 100 个压缩 .las 文件的文件夹,我希望有一种简单的方法来批量解压缩它们。我尝试了以下脚本

import os, zipfile

folder = 'D:/GISData/LiDAR/SomeFolder'
extension = ".zip"

for item in os.listdir(folder):
    if item.endswith(extension):
        zipfile.ZipFile.extract(item)

但是,当我运行脚本时,我收到以下错误:

Traceback (most recent call last):
  File "D:/GISData/Tools/MO_Tools/BatchUnzip.py", line 10, in <module>
    extract = zipfile.ZipFile.extract(item)
TypeError: unbound method extract() must be called with ZipFile instance as first argument (got str instance instead)

我正在使用 python 2.7.5 解释器。我查看了 zipfile 模块 (https://docs.python.org/2/library/zipfile.html#module-zipfile) 的文档,我想了解我做错了什么。

在我看来,这个过程会是这样的:

  1. 获取文件夹名称
  2. 遍历文件夹并找到 zip 文件
  3. 将 zip 文件解压到文件夹

感谢 Marcus,但是,在实施建议时,我收到另一个错误:

Traceback (most recent call last):
  File "D:/GISData/Tools/MO_Tools/BatchUnzip.py", line 12, in <module>
    zipfile.ZipFile(item).extract()
  File "C:\Python27\ArcGIS10.2\lib\zipfile.py", line 752, in __init__
    self.fp = open(file, modeDict[mode])
IOError: [Errno 2] No such file or directory: 'JeffCity_0752.las.zip'

当我使用打印语句时,我可以看到文件在那里。例如:

for item in os.listdir(folder):
    if item.endswith(extension):
        print os.path.abspath(item)
        filename = os.path.basename(item)
        print filename

产量:

D:\GISData\Tools\MO_Tools\JeffCity_0752.las.zip
JeffCity_0752.las.zip
D:\GISData\Tools\MO_Tools\JeffCity_0753.las.zip
JeffCity_0753.las.zip

据我了解文档,

zipfile.ZipFile(file[, mode[, compression[, allowZip64]]])

打开一个 ZIP 文件,其中 file 可以是文件的路径(字符串)或类似文件的对象

在我看来,一切都存在并得到了解释。我只是不明白我做错了什么。

有什么建议吗?

谢谢

【问题讨论】:

    标签: python python-2.7 unzip zipfile arcpy


    【解决方案1】:

    你需要用文件名构造一个ZipFile对象,然后然后解压它:

        zipfile.ZipFile.extract(item)
    

    错了。

        zipfile.ZipFile(item).extractall()
    

    将从压缩文件中提取名称包含在item 中的所有文件。

    我认为你应该更仔细地阅读zipfile 的文档:) 但你走在正确的轨道上!

    【讨论】:

    【解决方案2】:

    以下是对我有用的代码:

    import os, zipfile
    
    dir_name = 'C:\\SomeDirectory'
    extension = ".zip"
    
    os.chdir(dir_name) # change directory from working dir to dir with files
    
    for item in os.listdir(dir_name): # loop through items in dir
        if item.endswith(extension): # check for ".zip" extension
            file_name = os.path.abspath(item) # get full path of files
            zip_ref = zipfile.ZipFile(file_name) # create zipfile object
            zip_ref.extractall(dir_name) # extract file to dir
            zip_ref.close() # close file
            os.remove(file_name) # delete zipped file
    

    回头看我修改过的代码,目录与脚本目录混淆了。

    以下方法在不破坏工作目录的情况下也有效。首先删除该行

    os.chdir(dir_name) # change directory from working dir to dir with files
    

    然后将file_name赋值为

    file_name = dir_name + "/" + item
    

    【讨论】:

    • 感谢朋友的解释!!我的问题是,我提取的所有文件内部都有相同的文件名,当我使用 extractall 时,它会直接破坏文件,只留下最后一个。我应该更改它的名称,但我不知道如何。 @陈露
    • @Borja_042 我建议创建一个计数变量,然后将其添加到提取时的文件名中。在循环内部,将 count 变量附加到目录名称。
    • 如果我想解压文件夹和子文件夹中的zip文件怎么办?
    【解决方案3】:

    接受的答案效果很好!

    只是为了扩展想法以解压缩目录内所有子目录中所有扩展名为 .zip 的文件,以下代码似乎运行良好:

    import os
    import zipfile
    
    for path, dir_list, file_list in os.walk(dir_path):
        for file_name in file_list:
            if file_name.endswith(".zip"):
                abs_file_path = os.path.join(path, file_name)
    
                # The following three lines of code are only useful if 
                # a. the zip file is to unzipped in it's parent folder and 
                # b. inside the folder of the same name as the file
    
                parent_path = os.path.split(abs_file_path)[0]
                output_folder_name = os.path.splitext(abs_file_path)[0]
                output_path = os.path.join(parent_path, output_folder_name)
    
                zip_obj = zipfile.ZipFile(abs_file_path, 'r')
                zip_obj.extractall(output_path)
                zip_obj.close()
    

    【讨论】:

      【解决方案4】:

      我认为这更短,对我来说效果很好。首先导入需要的模块:

      import zipfile, os
      

      然后,我定义工作目录:

      working_directory = 'my_directory'
      os.chdir(working_directory)
      

      之后,您可以使用oszipfile 的组合来到达您想要的位置:

      for file in os.listdir(working_directory):   # get the list of files
          if zipfile.is_zipfile(file): # if it is a zipfile, extract it
              with zipfile.ZipFile(file) as item: # treat the file as a zip
                 item.extractall()  # extract it in the working directory
      

      【讨论】:

      • 这个解决方案对我有用。它也比公认的答案更 Pythonic。
      • 简短而简单的答案是最好的!
      【解决方案5】:

      递归版本的@tpdance answer

      将此用于子文件夹 和子文件夹。使用 Python 3.8

      import os
      import zipfile
      
      base_dir = '/Users/john/data' # absolute path to the data folder
      extension = ".zip"
      
      os.chdir(base_dir)  # change directory from working dir to dir with files
      
      
      def unpack_all_in_dir(_dir):
          for item in os.listdir(_dir):  # loop through items in dir
              abs_path = os.path.join(_dir, item)  # absolute path of dir or file
              if item.endswith(extension):  # check for ".zip" extension
                  file_name = os.path.abspath(abs_path)  # get full path of file
                  zip_ref = zipfile.ZipFile(file_name)  # create zipfile object
                  zip_ref.extractall(_dir)  # extract file to dir
                  zip_ref.close()  # close file
                  os.remove(file_name)  # delete zipped file
              elif os.path.isdir(abs_path):
                  unpack_all_in_dir(abs_path)  # recurse this function with inner folder
      
      
      unpack_all_in_dir(base_dir)
      

      【讨论】: