web-dev-qa-db-ja.com

python ZipFile?

1つのフォルダーにサブフォルダーを含む.Zipからすべてのファイルを抽出しようとしました。サブフォルダーのすべてのファイルを、元の構造を保持せずに1つのフォルダーのみに抽出する必要があります。現時点では、すべてを抽出し、ファイルをフォルダーに移動してから、以前のサブフォルダーを削除します。同じ名前のファイルは上書きされます。

ファイルを書き込む前にそれを行うことは可能ですか?

以下に例を示します。

my_Zip/file1.txt
my_Zip/dir1/file2.txt
my_Zip/dir1/dir2/file3.txt
my_Zip/dir3/file4.txt

最後に私はこれをかき立てます:

my_dir/file1.txt
my_dir/file2.txt
my_dir/file3.txt
my_dir/file4.txt

このコードに何を追加できますか?

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()

zip_file.namelist()からファイルパスの名前を変更すると、次のエラーが発生します。

KeyError: "There is no item named 'file2.txt' in the archive"
40
Thammas

これにより、Zipアーカイブのメンバーのファイルハンドルが開き、ファイル名が抽出されてターゲットファイルにコピーされます(そのようにZipFile.extractは機能しますが、サブディレクトリは考慮されません)。

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 = open(os.path.join(my_dir, filename), "wb")
        with source, target:
            shutil.copyfileobj(source, target)
54
Reiner Gerecke

ZipFile.infolist()を反復処理することができます。返されたZipInfoオブジェクトで、filenameを操作してディレクトリ部分を削除し、最終的に指定されたディレクトリに抽出できます。

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)
13
Gerhard Götz

メモリ内のバイトに抽出し、ファイル名を計算し、ライブラリに実行させるのではなく、自分で書き込みます--ほとんどの場合、「extract()」メソッドの代わりに「read()」を使用します

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()
8
jsbueno

GerhardGötzのソリューション と同様の概念ですが、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)))
1
L0laapk3