2011-02-07 50 views
27

我嘗試從包含一個文件夾中的子文件夾的.zip中提取所有文件。我希望所有來自子文件夾的文件只在一個文件夾中提取,而不保留原始結構。目前,我提取所有文件,將文件移動到一個文件夾,然後刪除以前的子文件夾。具有相同名稱的文件被盜用。從zip中提取文件而不保留使用python ZipFile的結構?

在寫文件之前可以做到嗎?

這裏的結構。例如:

my_zip/file1.txt 
my_zip/dir1/file2.txt 
my_zip/dir1/dir2/file3.txt 
my_zip/dir3/file4.txt 

最後我嘩嘩的:

my_dir/file1.txt 
my_dir/file2.txt 
my_dir/file3.txt 
my_dir/file4.txt 

我可以添加什麼代碼?

import zipfile 
my_dir = "D:\\Download\\" 
my_zip = "D:\\Download\\my_file.zip" 

zip_file = zipfile.ZipFile(my_zip, 'r') 
for files in zip_file.namelist(): 
    zip_file.extract(files, my_dir) 
zip_file.close() 

如果我重命名文件從zip_file.namelist()的路徑,我有這樣的錯誤:

KeyError: "There is no item named 'file2.txt' in the archive" 

回答

41

這將打開zip壓縮包成員的文件句柄,提取的F ilename並將其複製到目標文件(這就是ZipFile.extract的工作原理,不需要照顧子目錄)。

import os 
import shutil 
import zipfile 

my_dir = r"D:\Download" 
my_zip = r"D:\Download\my_file.zip" 

with zipfile.ZipFile(my_zip) as zip_file: 
    for member in zip_file.namelist(): 
     filename = os.path.basename(member) 
     # skip directories 
     if not filename: 
      continue 

     # copy file (taken from zipfile's extract) 
     source = zip_file.open(member) 
     target = file(os.path.join(my_dir, filename), "wb") 
     with source, target: 
      shutil.copyfileobj(source, target) 
+0

謝謝你的作品 – Thammas 2011-02-07 02:21:30

7

只需提取到內存字節計算的文件名,並寫有你自己,而不是 讓圖書館的辦呢 - -mostly,只需使用「閱讀()」而不是「提取物()」方法:

import zipfile 
import os 

my_dir = "D:\\Download\\" 
my_zip = "D:\\Download\\my_file.zip" 

zip_file = zipfile.ZipFile(my_zip, 'r') 
for files in zip_file.namelist(): 
    data = zip_file.read(files, my_dir) 
    # I am almost shure zip represents directory separator 
    # char as "/" regardless of OS, but I don't have DOS or Windos here to test it 
    myfile_path = os.path.join(my_dir, files.split("/")[-1]) 
    myfile = open(myfile_path, "wb") 
    myfile.write(data) 
    myfile.close() 
zip_file.close() 
+0

謝謝你。我必須添加一個異常以避免myfile_path中的目錄\並僅保留文件。 – Thammas 2011-02-07 02:26:21

2

可以遍歷ZipFile.infolist()。在返回的ZipInfo對象上,然後可以操作filename以刪除目錄部分,並最終將其提取到指定的目錄。

import glob 
import zipfile 
import shutil 
import os 

my_dir = "D:\\Download\\" 
my_zip = "D:\\Download\\my_file.zip" 

with zipfile.ZipFile(my_zip) as zip: 
    for zip_info in zip.infolist(): 
     if zip_info.filename[-1] == '/': 
      continue 
     zip_info.filename = os.path.basename(zip_info.filename) 
     zip.extract(zip_info, my_dir) 
相關問題