password - zipfile python 3
¿Extrae archivos de zip sin mantener la estructura usando python ZipFile? (3)
Intento extraer todos los archivos de .zip que contienen subcarpetas en una carpeta. Quiero que todos los archivos de las subcarpetas se extraigan en una sola carpeta sin mantener la estructura original. Por el momento, extraigo todo, muevo los archivos a una carpeta y luego elimino las subcarpetas anteriores. Los archivos con los mismos nombres se sobrescriben.
¿Es posible hacerlo antes de escribir archivos?
Aquí hay una estructura por ejemplo:
my_zip/file1.txt
my_zip/dir1/file2.txt
my_zip/dir1/dir2/file3.txt
my_zip/dir3/file4.txt
Al final, me gustaría esto:
my_dir/file1.txt
my_dir/file2.txt
my_dir/file3.txt
my_dir/file4.txt
¿Qué puedo agregar a este código?
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 renombro la ruta de los archivos desde zip_file.namelist (), tengo este error:
KeyError: "There is no item named ''file2.txt'' in the archive"
Es posible iterar sobre ZipFile.infolist()
. En los objetos ZipInfo
devueltos, puede manipular el filename
del filename
para eliminar la parte del directorio y, finalmente, extraerlo a un directorio especificado.
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)
Esto abre los manejadores de archivos de los miembros del archivo zip, extrae el nombre del archivo y lo copia en un archivo de destino (así es como funciona ZipFile.extract
, sin tener que ocuparse de los subdirectorios).
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)
Simplemente extraiga a bytes en la memoria, calcule el nombre del archivo y escríbalo allí mismo, en lugar de dejar que la biblioteca lo haga, en su mayoría, use el método "read ()" en lugar de "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()