Python zip 文件并避免目录结构

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/27991745/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-19 02:34:49  来源:igfitidea点击:

zip file and avoid directory structure

pythonzip

提问by user1189851

I have a Python script that zips a file (new.txt).

我有一个压缩文件 ( new.txt)的 Python 脚本。

tofile =  "/root/files/result/"+file
targetzipfile = new.zip   # This is how I want my zip to look like
zf = zipfile.ZipFile(targetzipfile, mode='w')
try:
    #adding to archive
    zf.write(tofile)
finally:
    zf.close()

When I do this I get the zip file. But when I try to unzip the file I get the text file inside of a series of directories corresponding to the path of the file i.e I see a folder called rootin the resultdirectory and more directories within it, i.e. I have

当我这样做时,我得到了 zip 文件。但是,当我尝试解压缩文件,我得到了一系列对应于文件的路径,即我看到一个名为文件夹目录的文本文件,里面rootresult内它的目录和多个目录,即我有

/root/files/result/new.zip

/root/files/result/new.zip

and when I unzip new.zipI have a directory structure that looks like

当我解压缩时,new.zip我的目录结构看起来像

/root/files/result/root/files/result/new.txt.

Is there a way I can zip such that when I unzip I only get new.txt.

有没有一种方法可以压缩,这样当我解压缩时,我只能得到new.txt.

In other words I have /root/files/result/new.zipand when I unzip new.zip, it should look like

换句话说,我有/root/files/result/new.zip,当我解压缩时new.zip,它应该看起来像

/root/files/results/new.txt

采纳答案by user 12321

The zipfile.write()method takes an optional arcnameargument that specifies what the name of the file should be inside the zipfile

zipfile.write()方法采用一个可选arcname参数,该参数指定 zipfile 中文件的名称

I think you need to do a modification for the destination, otherwise it will duplicate the directory. Use :arcnameto avoid it. try like this:

我认为您需要对目的地进行修改,否则会重复目录。使用 :arcname来避免它。试试这样:

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

回答by aquil.abdullah

Check out the documentation for Zipfile.write.

查看Zipfile.write的文档。

ZipFile.write(filename[, arcname[, compress_type]]) Write the file named filename to the archive, giving it the archive name arcname (by default, this will be the same as filename, but without a drive letter and with leading path separators removed)

ZipFile.write(filename[, arcname[, compress_type]]) 将名为 filename 的文件写入存档,为其指定存档名称 arcname(默认情况下,这将与 filename 相同,但没有驱动器号和前导路径删除了分隔符)

https://docs.python.org/2/library/zipfile.html#zipfile.ZipFile.write

https://docs.python.org/2/library/zipfile.html#zipfile.ZipFile.write

Try the following:

请尝试以下操作:

import zipfile
import os
filename = 'foo.txt'

# Using os.path.join is better than using '/' it is OS agnostic
path = os.path.join(os.path.sep, 'tmp', 'bar', 'baz', filename)
zip_filename = os.path.splitext(filename)[0] + '.zip'
zip_path = os.path.join(os.path.dirname(path), zip_filename)

# If you need exception handling wrap this in a try/except block
with zipfile.ZipFile(zip_path, 'w') as zf:
    zf.write(path, zip_filename)

The bottom line is that if you do not supply an archive name then the filename is used as the archive name and it will contain the full path to the file.

最重要的是,如果您不提供存档名称,则文件名将用作存档名称,它将包含文件的完整路径。

回答by William A. Romero R.

To illustrate most clearly,

为了最清楚地说明,

directory structure:

目录结构:

/Users
 └── /user
 .    ├── /pixmaps
 .    │    ├── pixmap_00.raw
 .    │    ├── pixmap_01.raw
      │    ├── /jpeg
      │    │    ├── pixmap_00.jpg
      │    │    └── pixmap_01.jpg
      │    └── /png
      │         ├── pixmap_00.png
      │         └── pixmap_01.png
      ├── /docs
      ├── /programs
      ├── /misc
      .
      .
      .

Directory of interest: /Users/user/pixmaps

感兴趣的目录:/Users/user/pixmaps

First attemp

第一次尝试

import os
import zipfile

TARGET_DIRECTORY = "/Users/user/pixmaps"
ZIPFILE_NAME = "CompressedDir.zip"

def zip_dir(directory, zipname):
    """
    Compress a directory (ZIP file).
    """
    if os.path.exists(directory):
        outZipFile = zipfile.ZipFile(zipname, 'w', zipfile.ZIP_DEFLATED)

        for dirpath, dirnames, filenames in os.walk(directory):
            for filename in filenames:

                filepath   = os.path.join(dirpath, filename)
                outZipFile.write(filepath)

        outZipFile.close()




if __name__ == '__main__':
    zip_dir(TARGET_DIRECTORY, ZIPFILE_NAME)

ZIP file structure:

ZIP文件结构:

CompressedDir.zip
.
└── /Users
     └── /user
          └── /pixmaps
               ├── pixmap_00.raw
               ├── pixmap_01.raw
               ├── /jpeg
               │    ├── pixmap_00.jpg
               │    └── pixmap_01.jpg
               └── /png
                    ├── pixmap_00.png
                    └── pixmap_01.png

Avoiding the full directory path

避免完整目录路径

def zip_dir(directory, zipname):
    """
    Compress a directory (ZIP file).
    """
    if os.path.exists(directory):
        outZipFile = zipfile.ZipFile(zipname, 'w', zipfile.ZIP_DEFLATED)

        # The root directory within the ZIP file.
        rootdir = os.path.basename(directory)

        for dirpath, dirnames, filenames in os.walk(directory):
            for filename in filenames:

                # Write the file named filename to the archive,
                # giving it the archive name 'arcname'.
                filepath   = os.path.join(dirpath, filename)
                parentpath = os.path.relpath(filepath, directory)
                arcname    = os.path.join(rootdir, parentpath)

                outZipFile.write(filepath, arcname)

    outZipFile.close()




if __name__ == '__main__':
    zip_dir(TARGET_DIRECTORY, ZIPFILE_NAME)

ZIP file structure:

ZIP文件结构:

CompressedDir.zip
.
└── /pixmaps
     ├── pixmap_00.raw
     ├── pixmap_01.raw
     ├── /jpeg
     │    ├── pixmap_00.jpg
     │    └── pixmap_01.jpg
     └── /png
          ├── pixmap_00.png
          └── pixmap_01.png

回答by jinzy

zf.write(tofile)

to change

改变

zf.write(tofile, zipfile_dir)

for example

例如

zf.write("/root/files/result/root/files/result/new.txt", "/root/files/results/new.txt")

回答by Helenus the Seer

You can isolate just the file name of your sources files using:

您可以使用以下方法仅隔离源文件的文件名:

name_file_only= name_full_path.split(os.sep)[-1]

For example, if name_full_pathis /root/files/results/myfile.txt, then name_file_onlywill be myfile.txt. To zip myfile.txt to the root of the archive zf, you can then use:

例如,如果name_full_path/root/files/results/myfile.txt,那么name_file_only将会是myfile.txt。要将 myfile.txt 压缩到存档的根目录zf,您可以使用:

zf.write(name_full_path, name_file_only)

回答by hubert

I face the same problem and i solve it with writestr. You can use it like this:

我面临同样的问题,我用writestr. 你可以这样使用它:

zipObject.writestr(<filename> , <file data, bytes or string>)

zipObject.writestr(<filename> , <file data, bytes or string>)

回答by Simon Buus Jensen

The arcnameparameter in the write method specifies what will be the name of the file inside the zipfile:

arcnamewrite 方法中的参数指定 zipfile 中文件的名称:

import os
import zipfile

# 1. Create a zip file which we will write files to
zip_file = "/home/username/test.zip"
zipf = zipfile.ZipFile(zip_file, 'w', zipfile.ZIP_DEFLATED)

# 2. Write files found in "/home/username/files/" to the test.zip
files_to_zip = "/home/username/files/"
for file_to_zip in os.listdir(files_to_zip):

    file_to_zip_full_path = os.path.join(files_to_zip, file_to_zip)

    # arcname argument specifies what will be the name of the file inside the zipfile
    zipf.write(filename=file_to_zip_full_path, arcname=file_to_zip)

zipf.close()