Python 3.x 如何在不解压缩的情况下将zip文件复制到文件夹?

Python 3.x 如何在不解压缩的情况下将zip文件复制到文件夹?,python-3.x,zip,zipfile,shutil,Python 3.x,Zip,Zipfile,Shutil,如何使该代码工作? 有一个包含文件夹和.png文件的zip文件。文件夹“\icons\u by\u year”为空。我需要一个接一个地获取每个文件,而无需解压缩,然后将其复制到所选文件夹的根目录下(这样就不会生成额外的文件夹) 我将看一看库的getinfo()和ZipFile.Path()的构造,因为如果您打算进行任何创建,构造函数类也可以以这种方式使用路径 具体地说。这可以做的就是构造一个包含路径的对象,它看起来是基于pathlib的。假设不需要创建ZipFile,可以忽略此ZipFile.P

如何使该代码工作? 有一个包含文件夹和.png文件的zip文件。文件夹“\icons\u by\u year”为空。我需要一个接一个地获取每个文件,而无需解压缩,然后将其复制到所选文件夹的根目录下(这样就不会生成额外的文件夹)

我将看一看库的getinfo()和ZipFile.Path()的构造,因为如果您打算进行任何创建,构造函数类也可以以这种方式使用路径

具体地说。这可以做的就是构造一个包含路径的对象,它看起来是基于pathlib的。假设不需要创建ZipFile,可以忽略此ZipFile.Path()

然而,这并不是我想要指出的。而是考虑以下内容:

zipfile.getinfo()

我认为有一个人正处于这种情况:


此人似乎正在使用getinfo()获取路径。很明显,并非每个zipfile都有该信息。

shutil.copyfileobj
将文件对象用于源文件和目标文件。要打开目标,需要为其构造文件路径
pathlib
是标准python库的一部分,是处理文件路径的好方法。和
ZipFile.extract
执行一些为您创建中间输出目录的工作(加上设置文件元数据),可以用来代替
copyfileobj

解压缩文件的一个风险是,它们可能包含目标目录之外的绝对或相对路径(例如“../../badvirus.exe”)
extract
在这方面有点太宽松了——将这些文件放在目标目录的根目录中——所以我写了一些东西,如果你被弄乱了,可以拒绝整个zip

用几个Tweek使它成为一个可测试的程序

from pathlib import Path
import re
import zipfile
#import shutil

#class ArrangerOutZip(Arranger):
class ArrangerOutZip:
    def __init__(self, base_source_folder, base_output_folder):
        self.base_source_folder = Path(base_source_folder).resolve(strict=True)
        self.base_output_folder = Path(base_output_folder).resolve()

    def proceed(self):
        self.create_and_copy()

    def create_and_copy(self):
        """Unzip files matching pattern to base_output_folder, raising
        ValueError if any resulting paths are outside of that folder.
        Output folder created if it does not exist."""
        reg_pattern = re.compile('.+\.\w{1,4}$')
        with open(self.base_source_folder, 'rb') as f:
            with zipfile.ZipFile(f) as zfile:
                wanted_files = [cont for cont in zfile.namelist()
                    if reg_pattern.match(cont)]
                rebased_files = self._rebase_paths(wanted_files,
                    self.base_output_folder)
                for cont, rebased in zip(wanted_files, rebased_files):
                    print(cont, rebased, rebased.parent)
                    # option 1: use shutil
                    #rebased.parent.mkdir(parents=True, exist_ok=True)
                    #with zfile.open(cont) as file, open(rebased, 'wb') as outfile:
                    #    shutil.copyfileobj(file, outfile)
                    # option 2: zipfile does the work for you
                    zfile.extract(cont, self.base_output_folder)
                    
    @staticmethod
    def _rebase_paths(pathlist, target_dir):
        """Rebase relative file paths to target directory, raising
        ValueError if any resulting paths are not within target_dir"""
        target = Path(target_dir).resolve()
        newpaths = []
        for path in pathlist:
            newpath = target.joinpath(path).resolve()
            newpath.relative_to(target) # raises ValueError if not subpath
            newpaths.append(newpath)
        return newpaths


#arranger = ArrangerOutZip('\\icons.zip', '.\\icons_by_year')

import sys
try:
    arranger = ArrangerOutZip(sys.argv[1], sys.argv[2])
    arranger.proceed()
except IndexError:
    print("usage: test.py zipfile targetdir")

这回答了你的问题吗@不幸的是,没有。我知道如何在两个文件夹之间复制文件。这里的任务是从zip存档文件中逐个复制文件,并将其粘贴到正确创建的文件夹中。文件夹可以像在父类中一样创建,但是我找不到一个正确的解决方案来直接绕过解压从zip文件复制。试试看,出了什么问题?是否有回溯消息?问题是
info.filename
是zipfile中的路径,而不是您的文件系统。您只能在zipfile打开时复制该文件。您可以使用
zf.extract
甚至
shutil.copyfileobj(zf.open(“任意”),other_fp)
但是由于路径不在您的文件系统上,
shutil.copy2
肯定会失败。我不知道如何重新排列您的代码,以便在
中使用open(…)作为zf进行复制,但这就是需要发生的事情。我相信在这个cod附近有一个答案,但我无法使它在我的代码中工作:
使用ZipFile(“source”,“r”)作为zf:使用zf.open(“destination”,“w”)作为条目:shutil.copyfileobj(source,destination)
我更改了主要问题。我更接近解决方案。您现在可以看一下吗?我相信我在shutil.copyfileobj中传递了错误的数据作为第二个属性。但我不知道如何正确执行此操作=(
from pathlib import Path
import re
import zipfile
#import shutil

#class ArrangerOutZip(Arranger):
class ArrangerOutZip:
    def __init__(self, base_source_folder, base_output_folder):
        self.base_source_folder = Path(base_source_folder).resolve(strict=True)
        self.base_output_folder = Path(base_output_folder).resolve()

    def proceed(self):
        self.create_and_copy()

    def create_and_copy(self):
        """Unzip files matching pattern to base_output_folder, raising
        ValueError if any resulting paths are outside of that folder.
        Output folder created if it does not exist."""
        reg_pattern = re.compile('.+\.\w{1,4}$')
        with open(self.base_source_folder, 'rb') as f:
            with zipfile.ZipFile(f) as zfile:
                wanted_files = [cont for cont in zfile.namelist()
                    if reg_pattern.match(cont)]
                rebased_files = self._rebase_paths(wanted_files,
                    self.base_output_folder)
                for cont, rebased in zip(wanted_files, rebased_files):
                    print(cont, rebased, rebased.parent)
                    # option 1: use shutil
                    #rebased.parent.mkdir(parents=True, exist_ok=True)
                    #with zfile.open(cont) as file, open(rebased, 'wb') as outfile:
                    #    shutil.copyfileobj(file, outfile)
                    # option 2: zipfile does the work for you
                    zfile.extract(cont, self.base_output_folder)
                    
    @staticmethod
    def _rebase_paths(pathlist, target_dir):
        """Rebase relative file paths to target directory, raising
        ValueError if any resulting paths are not within target_dir"""
        target = Path(target_dir).resolve()
        newpaths = []
        for path in pathlist:
            newpath = target.joinpath(path).resolve()
            newpath.relative_to(target) # raises ValueError if not subpath
            newpaths.append(newpath)
        return newpaths


#arranger = ArrangerOutZip('\\icons.zip', '.\\icons_by_year')

import sys
try:
    arranger = ArrangerOutZip(sys.argv[1], sys.argv[2])
    arranger.proceed()
except IndexError:
    print("usage: test.py zipfile targetdir")