2009-02-04 21 views
30

के साथ ज़िपफाइल से फ़ाइल हटाएं एक ज़िप्फ़ाइल से फ़ाइल हटाने के लिए एकमात्र तरीका यह था कि फ़ाइल को हटाए बिना अस्थायी ज़िपफाइल बनाना था और फिर इसे मूल फ़ाइल नाम पर पुनर्नामित करना था।ज़िपफाइल मॉड्यूल

पायथन 2.4 में ज़िपइन्फो क्लास में file_offset विशेषता थी, इसलिए दूसरी ज़िप फ़ाइल बनाना संभव था और बिना किसी डिकंप्रेस/रीकंप्रेसिंग के डेटा को अन्य फ़ाइल में कॉपी करना संभव था।

यह file_offset पायथन 2.6 में गायब है, तो क्या हर फ़ाइल को असम्पीडित करके एक और ज़िपफाइल बनाने और फिर इसे फिर से दबाकर एक और विकल्प है?

क्या ज़िपफाइल में फ़ाइल को हटाने का कोई प्रत्यक्ष तरीका हो सकता है, मैंने खोज की और कुछ भी नहीं मिला।

+0

मैं अजगर बग ट्रैकर एक ज़िप फ़ाइल से फ़ाइलों को हटाने की कठिनाइयों पर चर्चा पर इस सूत्र मिल गया। संगठन/अंक 6818 –

उत्तर

34

निम्नलिखित स्निपेट मेरे लिए काम किया (एक ज़िप संग्रह से सभी * .exe फ़ाइलों को हटा देता):

zin = zipfile.ZipFile ('archive.zip', 'r') 
zout = zipfile.ZipFile ('archve_new.zip', 'w') 
for item in zin.infolist(): 
    buffer = zin.read(item.filename) 
    if (item.filename[-4:] != '.exe'): 
     zout.writestr(item, buffer) 
zout.close() 
zin.close() 

आप स्मृति में सब कुछ पढ़ा है, तो आप एक दूसरे फ़ाइल की आवश्यकता को समाप्त कर सकते हैं। हालांकि, यह स्निपेट सब कुछ recompresses।

करीब निरीक्षण के बाद ZipInfo.header_offset फ़ाइल प्रारंभ से ऑफसेट है। नाम भ्रामक है, लेकिन मुख्य ज़िप हेडर वास्तव में फ़ाइल के अंत में संग्रहीत है। मेरा हेक्स संपादक इसकी पुष्टि करता है।

तो जिस समस्या में आप भाग लेंगे वह निम्न है: आपको मुख्य शीर्षलेख में निर्देशिका प्रविष्टि को भी हटाना होगा या यह उस फ़ाइल को इंगित करेगा जो अब मौजूद नहीं है। मुख्य हेडर बरकरार रखने से काम हो सकता है यदि आप उस फ़ाइल के स्थानीय शीर्षलेख को भी रखते हैं जिसे आप हटा रहे हैं, लेकिन मुझे इसके बारे में निश्चित नहीं है। पुराने मॉड्यूल के साथ आप इसे कैसे करते थे?

मुख्य हेडर को संशोधित किए बिना मुझे इसे खोलने पर "ज़िप Xil में X बाइट्स गायब" त्रुटि मिलती है। This आपको मुख्य हेडर को संशोधित करने का तरीका जानने में मदद कर सकता है।

+0

धन्यवाद, लेकिन अगर मैं गलत नहीं हूं - जब आप zipfile.writestr पर एक नज़र डालेंगे तो आप देखेंगे कि यह सिर्फ एक recompress है। पहले से संपीड़ित फ़ाइलों को बिना किसी संपीड़न के कॉपी करना और फिर उन्हें फिर से संपीड़ित करना बहुत तेज़ होगा। – RSabet

+0

@RSabt मैं एमडीएम से सहमत हूं कि unzip-and-rezip अब तक एकमात्र व्यवहार्य विकल्प है। वैसे, यह इंगित करना चाहते हैं कि एमडीएम कोड मदद करता है, लेकिन जब आप कुछ और गंभीरता से करेंगे तो os.path.splitext() का बेहतर उपयोग करें। – RayLuo

+1

var नाम के लिए +1 zin zout = D –

0

ruamel.std.zipfile से नियमित delete_from_zip_file ¹ आपको ज़िप के भीतर अपने पूर्ण पथ के आधार पर फ़ाइल को हटाने या (re) पैटर्न के आधार पर फ़ाइल को हटाने की अनुमति देता है। जैसे आप

from ruamel.std.zipfile import delete_from_zip_file 

delete_from_zip_file('test.zip', pattern='.*.exe') 

का उपयोग कर test.zip से .exe फ़ाइलों के सभी नष्ट कर सकते हैं (कृपया ध्यान दें * से पहले डॉट)।

यह एमडीएम के समाधान (रीकंप्रेशन की आवश्यकता सहित) के समान काम करता है, लेकिन ज़िप फ़ाइल को स्मृति में दोहराता है (कक्षा InMemZipFile() का उपयोग करके), पुरानी फ़ाइल को पूरी तरह से पढ़ने के बाद ओवरराइट करना।


¹ अस्वीकरण: मुझे लगता है कि पैकेज के लेखक हूँ।

2

बहुत ही सुंदर नहीं है, लेकिन यह कैसे मैंने किया है: https:: //bugs.python

import subprocess 
import zipfile 

z = zipfile.ZipFile(zip_filename) 

files_to_del = filter(lambda f: f.endswith('exe'), z.namelist()] 

cmd=['zip', '-d', zip_filename] + files_to_del 
subprocess.check_call(cmd) 

# reload the modified archive 
z = zipfile.ZipFile(zip_filename) 
+0

यही वह है जो मैंने किया। बदसूरत, लेकिन 'ZipFile' में फ़ाइलों को हटाने या अपडेट करने/बदलने का कोई तरीका प्रतीत नहीं होता है। – ArtOfWarfare

संबंधित मुद्दे