J'essaie d'extraire tous les fichiers de .Zip contenant des sous-dossiers dans un dossier. Je souhaite que tous les fichiers des sous-dossiers soient extraits dans un seul dossier sans conserver la structure d'origine. Pour le moment, je les extrait tous, déplace les fichiers dans un dossier, puis supprime les sous-dossiers précédents. Les fichiers portant le même nom sont écrasés.
Est-il possible de le faire avant d'écrire des fichiers?
Voici une structure par exemple:
my_Zip/file1.txt
my_Zip/dir1/file2.txt
my_Zip/dir1/dir2/file3.txt
my_Zip/dir3/file4.txt
À la fin, je souhaite ceci:
my_dir/file1.txt
my_dir/file2.txt
my_dir/file3.txt
my_dir/file4.txt
Que puis-je ajouter à ce code?
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()
si je renomme le chemin des fichiers de Zip_file.namelist (), j'ai cette erreur:
KeyError: "There is no item named 'file2.txt' in the archive"
Cela ouvre les descripteurs de fichiers des membres de l’archive Zip, extrait le nom du fichier et le copie dans un fichier cible (c’est ainsi que ZipFile.extract
fonctionne, sans se préoccuper des sous-répertoires).
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)
Il est possible de parcourir la ZipFile.infolist()
. Sur les objets ZipInfo
retournés, vous pouvez ensuite manipuler filename
pour supprimer la partie de répertoire et l'extraire dans un répertoire spécifié.
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)
Extrayez simplement les octets en mémoire, calculez le nom du fichier et écrivez-le vous-même, Au lieu de laisser la bibliothèque le faire -, utilisez la méthode "read ()" au lieu de la méthode "extract ()":
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()
Un concept similaire à la solution de Gerhard Götz , mais adapté pour extraire des fichiers uniques à la place de la totalité du Zip:
with ZipFile(zipPath, 'r') as zipObj:
zipInfo = zipObj.getinfo(path_in_Zip))
zipInfo.filename = os.path.basename(destination)
zipObj.extract(zipInfo, os.path.dirname(os.path.realpath(destination)))