2011-02-07 33 views
27

Tôi cố gắng trích xuất tất cả các tệp từ .zip chứa thư mục con trong một thư mục. Tôi muốn tất cả các tệp từ thư mục con được trích xuất chỉ trong một thư mục mà không giữ cấu trúc ban đầu. Tại thời điểm này, tôi trích xuất tất cả, di chuyển các tập tin vào một thư mục, sau đó loại bỏ các thư mục con trước đó. Các tệp có cùng tên sẽ bị ghi đè.Trích xuất tệp từ zip mà không cần giữ cấu trúc bằng cách sử dụng python ZipFile?

Có thể làm điều đó trước khi ghi tệp không?

Dưới đây là một cấu trúc ví dụ:

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

Cuối cùng tôi whish này:

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

tôi có thể thêm gì để mã này?

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

nếu tôi đổi tên file đường đi từ zip_file.namelist(), tôi có lỗi này:

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

Trả lời

41

này mở ra xử lý tập tin của các thành viên của các kho lưu trữ zip, chiết xuất từ ​​các f ilename và sao chép nó vào một tệp mục tiêu (đó là cách hoạt động của ZipFile.extract, mà không được chăm sóc bởi các thư mục con).

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

Cảm ơn bạn nó hoạt động – Thammas

7

Chỉ cần giải nén vào byte trong bộ nhớ, tính filename, và viết nó ở đó cho mình, thay vì để cho thư viện làm điều đó - -mostly, chỉ cần sử dụng "read()" thay vì "giải nén()" phương pháp:

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

Cảm ơn bạn. Tôi chỉ cần thêm một ngoại lệ để tránh thư mục \ trong myfile_path và chỉ giữ các tệp. – Thammas

2

Có thể lặp qua ZipFile.infolist(). Trên các đối tượng ZipInfo trả về, bạn có thể thao tác filename để xóa phần thư mục và cuối cùng giải nén nó vào một thư mục được chỉ định.

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) 
Các vấn đề liên quan