Как добавить файлы из нескольких zip-файлов в один zip-файл - PullRequest
1 голос
/ 08 ноября 2019

Я хочу поместить файлы из нескольких zip-файлов, имеющих общую подстроку, в один zip-файл

У меня есть папка «temp», содержащая некоторые файлы .zip и некоторые другие файлы

filename1_160645.zip
filename1_165056.zip
filename1_195326.zip
filename2_120528.zip
filename2_125518.zip
filename3_171518.zip
test.xlsx
filename19_161518.zip

У меня есть следующий файл данных df_filenames, содержащий префиксы имени файла

filename_prefix

filename1
filename2
filename3

, если в папке temp есть несколько файлов .zip с тем же префиксом, который существует в файле данных df_filenames, я хочу объединить содержимоеэти файлы

, например filename1_160645.zip содержит следующее содержимое

1a.csv
1b.csv

, а filename1_165056.zip содержит следующее содержимое

1d.csv

, а filename1_195326.zip содержит следующее содержимое

1f.csv

после слияния содержимого 2 вышеуказанных файлов в filename1_160645.zip содержимое filename1_160645.zip будет

1a.csv
1b.csv
1d.csv
1f.csv

В конце, только следующие файлы останутся временной папкой

filename1_160645.zip
filename2_120528.zip
filename3_171518.zip
test.xlsx
filename19_161518.zip

Я написал следующий код, но он не работает


import os
import zipfile as zf
import pandas as pd

df_filenames=pd.read_excel('filename_prefix.xlsx')
#Get the list of all the filenames in the temp folder
lst_fnames=os.listdir(r'C:\Users\XYZ\Downloads\temp')
#take only .zip files
lst_fnames=[fname for fname in lst_fnames if fname.endswith('.zip')]

#take distinct prefixes in the dataframe
df_prefixes=df_filenames['filename_prefix'].unique()

for prefix in df_prefixes:
    #this list will contain zip files with the same prefixes
    lst=[]

    #total count of files in the lst
    count=0
    for fname in lst_fnames:
        if prefix in fname:
            #print(prefix)
            lst.append(fname)
            #print(lst)
    #if the list has more than 1 zip files,merge them
    if len(lst)>1:
        print(lst)
        with zf.ZipFile(lst[0], 'a') as f1:
            print(f1.filename)
            for f in lst[1:]:

                with zf.ZipFile(path+'\\'+f, 'r') as f:
                    print(f.filename) #getting entire path of the file here,not just filename
                    [f1.writestr(t[0], t[1].read()) for t in ((n, f.open(n)) for n in f.namelist())]
                    print(f1.namelist())

после объединения содержимого файлов с именем файла, содержащим filename1, в tон filename1_160645.zip, содержимое `` filename1_160645.zip``` должно быть

1a.csv
1b.csv
1d.csv
1f.csv

, но ничего не изменилось, когда я дважды щелкнул filename1_160645.zip В основном, 1a.csv, 1b.csv, 1d.csv, 1f.csv не являются частью filename1_160645.zip

1 Ответ

1 голос
/ 08 ноября 2019

Я бы использовал shutil для просмотра более высокого уровня при работе с архивными файлами. Кроме того, использование pathlib дает хорошие методы / атрибуты для заданного пути к файлу. В сочетании с groupby мы можем легко извлекать целевые файлы, которые связаны друг с другом.

import itertools
import shutil
from pathlib import Path
import pandas as pd

filenames = pd.read_excel('filename_prefix.xlsx')
prefixes = filenames['filename_prefix'].unique()

path = Path.cwd()  # or change to Path('path/to/desired/dir/')
zip_files = (file for file in path.iterdir() if file.suffix == '.zip')
target_files = sorted(file for file in zip_files 
                      if any(file.stem.startswith(pre) for pre in prefixes))

file_groups = itertools.groupby(target_files, key=lambda x: x.stem.split('_')[0])
for _, group in file_groups:
    first, *rest = group
    if not rest:
        continue

    temp_dir = path / first.stem
    temp_dir.mkdir()

    shutil.unpack_archive(first, extract_dir=temp_dir)
    for item in rest:
        shutil.unpack_archive(item, extract_dir=temp_dir)
        item.unlink()

    shutil.make_archive(temp_dir, 'zip', temp_dir)
    shutil.rmtree(temp_dir)
...