如何仅压缩文件夹内的文件而不压缩子文件夹?

Posted

技术标签:

【中文标题】如何仅压缩文件夹内的文件而不压缩子文件夹?【英文标题】:How to zip only the files inside the folder and not the sub folders? 【发布时间】:2016-08-30 12:08:55 【问题描述】:

我的文件夹结构为:

/sample/debug/
    --debug.exe
    --sample.exe
    --sample.pdb
    --debug.pdb
    --sample.dll
    --debug.dll
    /config
        --sample.txt
        --new.txt
    /general
        --general.txt
        --code.txt

所以,我想要的只是压缩 debug 中的文件,而不是像 /config 和 /general 这样的子文件夹。我尝试如下:

import zipfile
import os

def append( dir_name ):
    ret_val = []
    fileList = []
    for file in os.listdir(dir_name):
        try:
            dirfile = os.path.join(dir_name, file)
        except Exception:
            err = sys.exc_info()
            print ("Error!", err)
        fileList.append(dirfile)
        ret_val = fileList
    return ret_val

def zip( fileList, archive, root ):
    ret_val = 0
    try:
        zip_folder_contents = zipfile.ZipFile(archive, 'w', zipfile.ZIP_DEFLATED)
    except Exception:
        err = sys.exc_info()
        print ("Error!",err)
        exit( 1 )
    for filename in fileList:
        zip_folder_contents.write(filename,
                filename[len(root):].lstrip(os.path.sep).lstrip(os.path.altsep))
    zip_folder_contents.close()
    return ret_val

make(append_files_in_zipfolder("D:/sample/debug"), "debug.zip",
                               "D:/sample/debug")

现在当我在上面执行时,我收到错误,因为权限被拒绝“D:/sample/debug\\config”。因此,我无法删除此错误,因此我认为只包含 zip 文件夹中的文件并排除子文件夹。那么,无论如何,有没有办法做到这一点,或者我可以通过某种方式删除我得到的这个与权限相关的错误。请提出建议。

【问题讨论】:

什么是make()?函数append_files_in_zipfolder()的定义在哪里? 查看os模块的Files and Directories部分,选择一些可以帮助您清除目录的方法,制定一些清除目录的逻辑,将它们放在一起并压缩文件. os.walk 可能有点矫枉过正,但它可能会让事情变得简单。还有一些其他的可以使它变得容易/可能。 【参考方案1】:

您可以使用以下方法从文件夹中获取所有文件,而无需进入子文件夹:

import os
def getfilesfrom(directory):
    return filter(lambda x:
                  not os.path.isdir(os.path.join(directory, x)),
                  os.listdir(directory))

# or alternatively, using generators (as suggested in the comments):
def getfilesfrom(directory):
    for x in os.listdir(directory):
        if not os.path.isdir(os.path.join(directory, x)):
            yield x  # or yield os.path.join(directory, x) for full path.

然后您可以简单地运行(如documentation 中所述):

import datetime
import zipfile

def print_info(archive_name):
""" Print information from zip archive"""
zf = zipfile.ZipFile(archive_name)
for info in zf.infolist():
    print info.filename
    print '\tComment:\t', info.comment
    print '\tModified:\t', datetime.datetime(*info.date_time)
    print '\tSystem:\t\t', info.create_system, '(0 = Windows, 3 = Unix)'
    print '\tZIP version:\t', info.create_version
    print '\tCompressed:\t', info.compress_size, 'bytes'
    print '\tUncompressed:\t', info.file_size, 'bytes'
    print

print 'creating archive'
zf = zipfile.ZipFile('debug.zip', mode='a', compression=zipfile.ZIP_DEFLATED)
inputdir = '/sample/debug/'
filestozip = getfilesfrom(inputdir)
for afile in filestozip:
    print('adding ' + afile + ' to zipfile debug.zip')
    zf.write(os.path.join(inputdir, afile), afile)

print 'closing'
zf.close()

print
print_info('debug.zip')

【讨论】:

我按照建议进行了操作,但出现“系统找不到指定的文件”debug.exe 错误。在行'zf.write(afile)。 如果您尝试使用zf.write(os.path.join(inputdir, afile)),会解决问题吗?刚刚编辑了代码。我还将模式从'w' 更改为'a',否则你会在循环时覆盖文件。 我也这样做了,但现在我得到了 debug.zip 文件夹,它已经压缩了根目录中的所有文件夹,即 debug.zip 包含从“/sample/”根目录开始的文件夹,但我没有不希望完整的目录被压缩。我只想要压缩文件夹中的文件。我该怎么办 zf.write(os.path.join(inputdir, afile), afile) 如果您将getfilesfrom 设为生成器,它将占用相同数量的行但更易于阅读:for x in os.listdir(directory): if not os.path.isdir(os.path.join(directory, x): yield x 它还可以更容易地适应使其生成os.path.join(directory, x) 而不是单独的文件名。【参考方案2】:

以下使用了可用的新 ZipFile 上下文管理器:

from zipfile import ZipFile

def zip_folder(zip_name, folder):
    with ZipFile(zip_name, 'w') as myzip:
        for entry in os.listdir(folder):
            if os.path.isfile(entry):
                myzip.write(os.path.join(folder, entry), arcname=entry)

zip_folder(r'D:\output.zip', r'D:\sample\debug')

【讨论】:

以上是关于如何仅压缩文件夹内的文件而不压缩子文件夹?的主要内容,如果未能解决你的问题,请参考以下文章

仅使用 7z 压缩文件而不保留路径

如何用SAS读取压缩包内的文件或是自动解压文件

如何将2个压缩包内的文件解压到同一个文件夹

ZipInputStream - 解压缩文件的功能方法

如何使用 GZipStream 解压缩内存中的 gz 文件?

如何连接两个或多个 gzip 文件/流