Soru Python'da .zip oluşturun?


Komut dizimde belirli bir kaynak dizininin içeriğini gösteren bir işlev oluşturmaya çalışıyorum (src) bir zip dosyasına (dst). Örneğin, zip('/path/to/dir', '/path/to/file.zip'), nerede /path/to/dir bir dizin ve /path/to/file.zip henüz mevcut değil. ben yapma dizinin kendisini sıkıştırmak istiyorum, bu benim durumumdaki tüm farkları yaratıyor. Dizindeki dosyaları (ve alt dizinleri) sıkıştırmak istiyorum. Denediğim şey bu:

def zip(src, dst):
    zf = zipfile.ZipFile("%s.zip" % (dst), "w")
    for dirname, subdirs, files in os.walk(src):
        zf.write(dirname)
        for filename in files:
            zf.write(os.path.join(dirname, filename))
    zf.close()

Bu aslında bir zip oluşturur /. Örneğin, sıkıştırılmış olsaydım /path/to/dir, zip'i ayıklamak, içinde "yol" olan bir dizini, bu dizinde "to" ile, vb. oluşturur.

Kimsenin bu soruna neden olmayan bir işlevi var mı?

Bunu yeterince strese atamıyorum. ihtiyaçlar dizindeki dosyaları sıkıştırmak için, direktörlüğün kendisi değil.


32
2018-01-28 18:27


Menşei


Olası kopya Bir dizinin bir zip arşivi nasıl oluşturulur - BuZZ-dEE


Cevaplar:


zipfile.write() yöntem isteğe bağlı alır arcname tartışma dosyanın isminin zip dosyasında olması gerektiğini belirtir.

Bu yolu kaldırmak için kullanabilirsiniz src başlangıçta. İşte ben kullanım os.path.abspath() ikisinden de emin olmak için src ve dosya adı tarafından döndürüldü os.walk() ortak bir önek var.

#!/usr/bin/env python2.7

import os
import zipfile

def zip(src, dst):
    zf = zipfile.ZipFile("%s.zip" % (dst), "w", zipfile.ZIP_DEFLATED)
    abs_src = os.path.abspath(src)
    for dirname, subdirs, files in os.walk(src):
        for filename in files:
            absname = os.path.abspath(os.path.join(dirname, filename))
            arcname = absname[len(abs_src) + 1:]
            print 'zipping %s as %s' % (os.path.join(dirname, filename),
                                        arcname)
            zf.write(absname, arcname)
    zf.close()

zip("src", "dst")

Böyle bir dizin yapısı ile:

src
└── a
    ├── b
    │   └── bar
    └── foo

Komut yazdırır:

zipping src/a/foo as a/foo
zipping src/a/b/bar as a/b/bar

Ve sonuçta elde edilen zip dosyasının içeriği:

Archive:  dst.zip
  Length     Date   Time    Name
 --------    ----   ----    ----
        0  01-28-13 11:36   a/foo
        0  01-28-13 11:36   a/b/bar
 --------                   -------
        0                   2 files

53
2018-01-28 18:50



Umut verici görünüyor (DÜZENLEME: mükemmel çalışıyor), ama ithal etmek için herhangi bir sebep var mı os ve os.path? - tkbx
Evet-os için os.walk(), ve os.path için os.path.abspath() ve os.path.join(). - andrewdotn
@andrew senin erişimin var os.path ayrı olarak ithal etmeden. Bunu yapmanın asıl nedeni, şunun gibi yeniden adlandırırsanız import os.path as P ya da her neyse. - agoebel
@tkbx: from os import path koyar path en üst düzeyde, böylece yapabilirsin path.join yerine os.path.join. Bu genellikle yapmak istediğiniz şey değildir (özellikle herkesin her zaman bir değişkene sahip olduğu için) path kodlarında bir yere). - abarnert
Bu işlev iyi çalışır, ancak çoğu durumda beklenen davranış olan boş dosyaya zip dosyasına eklenmez. Başka bir deyişle, içinde dosya bulunmayan herhangi bir alt klasör göz ardı edilir. - bobyuan


Kullan arcname parametre zip dosyasındaki adı / yolu denetlemek için.

Örneğin, yalnızca dosyaları içeren bir zip dosyası için dizin yok:

zf.write(os.path.join(dirname, filename), arcname=filename)

Veya zip dosyasının içinde yeni bir dizin icat etmek için:

zf.write(os.path.join(dirname, filename), arcname=os.path.join("my_zip_dir", filename))

1
2018-01-28 18:46





Sana söyleyebildiğim kadar yakın. Kullanabilirsin dirname ve basename Doğru yol adını tuttuğunuzdan emin olmak için:

>>> os.path.dirname("/path/to/dst")
'/path/to'
>>> os.path.basename("/path/to/dst")
'dst'

Sonra kullanarak chdir Ebeveynler içinde olduğundan emin olabilirsiniz, böylece yollar görecelidir.

def zip(src, dst):
    parent = os.path.dirname(dst)
    folder = os.path.basename(dst)

    os.chdir(parent):
    for dirname, subdirs, filenames in os.walk(folder):
        ...

Bu oluşturur:

dst/a.txt
dst/b
dst/b/c.txt
...etc...

Eğer "dst" ismini eklemek istemezseniz os.chdir(dst) ve sonra os.walk('.').

Umarım yardımcı olur.


0
2018-01-28 18:38



Lütfen bunu not al zip aynı zamanda çok farklı amaçlarla yerleşik bir işlevdir: docs.python.org/2/library/functions.html#zip - Matteo T.