zipfile 解压缩到一个文件夹

zipfile extract zip to a folder

下面是文件结构

music_folder
    album1.zip (below are contents inside of zip)
        song1.mp3
        song2.mp3
        song3.mp3
    album2.zip (below are contents inside of zip)
        song12.mp3
        song14.mp3
        song16.mp3

我想将两个压缩相册解压到一个名为 cache 的目录中,并且我想要相同的结构。 这就是我想要的样子:

cache
    album1 (this is a normal unzipped folder)
        song1.mp3
        song2.mp3
        song3.mp3
    album2 (this is a normal unzipped folder)
        song12.mp3
        song14.mp3
        song16.mp3

但由于某些原因,对于 album1,文件直接提取到 cache 目录而不是 cache/album1

这就是它的样子,我不想要这个:

cache
    song1.mp3
    song2.mp3
    song3.mp3
    album2 (this is a normal unzipped folder)
        song12.mp3
        song14.mp3
        song16.mp3

下面是我的代码:

for zipped_album in os.listdir('music_folder'):
    zip_ref = ZipFile('music_folder/' + zipped_album, 'r')
    zip_ref.extractall('cache')
    zip_ref.close()

知道为什么 album1 的文件没有提取到 chache 内的文件夹中吗?它适用于 album2

Zip 文件可以包含(相对)路径名,而不仅仅是文件名。

所以,album2.zip的内容最有可能是:

  • album2/song1.mp3
  • album2/song2.mp3
  • album2/song3.mp3

... 但是 album1.zip 只是:

  • 歌曲1.mp3
  • 歌曲2.mp3
  • song3.mp3

要对此进行测试,您可以从 shell.

中执行 unzip -l album1.zipunzip -l album2.zip

这实际上是人们在共享 zip 文件时一直遇到的问题。您通常希望在路径中包含 album2,但有时它会丢失。您不想强行添加它并以 album2/album2/song1.mp3 结束,但您不想不添加它并最终在顶级目录中只得到 song1.mp3

现在大多数 GUI 工具使用的解决方案(我认为它可以追溯到古老的 Stuffit Expander)是这样的:

  • Iterate all of the zip entries 并查看路径名是否都以同一目录开头。
  • 如果是,请按原样解压缩。
  • 如果没有,创建一个与 zip 文件同名的目录(减去 .zip),然后将它们解压缩到该目录中。

一个棘手的地方是压缩文件路径可以是Windows或POSIX格式,它们可以是绝对路径或UNC路径甚至以..开头的路径,并且将这些路径转换为可用路径的逻辑虽然不完全是困难,但不仅仅是一行。因此,您必须决定要使您的代码完全通用化到什么程度。