2011-12-31 26 views
5

Tôi đang sử dụng mã hiện để trích xuất các tập tin từ một tập tin zip trong khi vẫn giữ cấu trúc thư mục:Extract file từ zip mà không cần giữ cho thư mục cấp cao nhất với python zipfile

zip_file = zipfile.ZipFile('archive.zip', 'r') 
zip_file.extractall('/dir/to/extract/files/') 
zip_file.close() 

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

/dir1/file.jpg 
/dir1/file1.jpg 
/dir1/file2.jpg 

cuối cùng tôi muốn điều này:

/dir/to/extract/file.jpg 
/dir/to/extract/file1.jpg 
/dir/to/extract/file2.jpg 

Nhưng nó nên tôi gnore chỉ khi file zip có một thư mục cấp cao nhất với tất cả các file bên trong nó, vì vậy khi tôi trích xuất một zip với cấu trúc này:

/dir1/file.jpg 
/dir1/file1.jpg 
/dir1/file2.jpg 
/dir2/file.txt 
/file.mp3 

Nó nên ở lại như thế này:

/dir/to/extract/dir1/file.jpg 
/dir/to/extract/dir1/file1.jpg 
/dir/to/extract/dir1/file2.jpg 
/dir/to/extract/dir2/file.txt 
/dir/to/extract/file.mp3 

Bất kỳ ý tưởng ?

Trả lời

1

Đọc các mục được trả về bởi ZipFile.namelist() để xem chúng có nằm trong cùng một thư mục hay không và sau đó mở/đọc từng mục nhập và ghi nó vào một tệp được mở bằng open().

0

Điều này có thể là vấn đề với bản lưu trữ zip. Trong dấu nhắc python, hãy thử điều này để xem các tệp có nằm trong các thư mục chính xác trong chính tệp zip hay không.

import zipfile 

zf = zipfile.ZipFile("my_file.zip",'r') 
first_file = zf.filelist[0] 
print file_list.filename 

này nên nói điều gì đó như "dir1" lặp lại các bước trên thay thế và chỉ số của 1 thành filelist như vậy first_file = zf.filelist[1] Lần này đầu ra sẽ giống như 'dir1/file1.jpg' nếu đây không phải là trường hợp sau đó tệp zip không chứa các thư mục và sẽ được giải nén tất cả vào một thư mục duy nhất.

4

Nếu tôi hiểu chính xác câu hỏi của bạn, bạn muốn loại bỏ bất kỳ thư mục tiền tố chung nào khỏi các mục trong zip trước khi giải nén chúng.

Nếu vậy, thì kịch bản sau đây nên làm những gì bạn muốn:

import sys, os 
from zipfile import ZipFile 

def get_members(zip): 
    parts = [] 
    # get all the path prefixes 
    for name in zip.namelist(): 
     # only check files (not directories) 
     if not name.endswith('/'): 
      # keep list of path elements (minus filename) 
      parts.append(name.split('/')[:-1]) 
    # now find the common path prefix (if any) 
    prefix = os.path.commonprefix(parts) 
    if prefix: 
     # re-join the path elements 
     prefix = '/'.join(prefix) + '/' 
    # get the length of the common prefix 
    offset = len(prefix) 
    # now re-set the filenames 
    for zipinfo in zip.infolist(): 
     name = zipinfo.filename 
     # only check files (not directories) 
     if len(name) > offset: 
      # remove the common prefix 
      zipinfo.filename = name[offset:] 
      yield zipinfo 

args = sys.argv[1:] 

if len(args): 
    zip = ZipFile(args[0]) 
    path = args[1] if len(args) > 1 else '.' 
    zip.extractall(path, get_members(zip)) 
+0

Bạn có thể thêm một số ý kiến ​​để hiểu rõ hơn về những gì đang xảy ra ở đây, xin vui lòng? – aturegano

+1

@aturegano. Tôi đã thêm một số nhận xét vào mã ví dụ. Các tên tệp của các đối tượng zipinfo có thể ghi được. Vì vậy, kịch bản sẽ rút tiền tố chung từ tất cả các tệp trong kho lưu trữ, trước khi giải nén chúng vào thư mục đích. – ekhumoro

Các vấn đề liên quan