【问题标题】:renaming the extracted file from zipfile重命名从 zipfile 提取的文件
【发布时间】:2017-10-20 03:59:24
【问题描述】:

我在 Linux 服务器上有很多压缩文件,每个文件都包含多个文本文件。

我想要的是提取其中一些文本文件,它们在压缩文件中具有相同的名称,并将其保存在一个文件夹中;我正在为每个压缩文件创建一个文件夹并将文本文件提取到其中。我需要将父压缩文件夹名称添加到文件名的末尾,并将所有文本文件保存在一个目录中。例如,如果压缩文件夹是 March132017.zip,我提取了 holding.txt,我的文件名将是 holding_march13207.txt。

我的问题是我无法更改提取文件的名称。 如果您能提供建议,我将不胜感激。

import os 
import sys 
import zipfile
os.chdir("/feeds/lipper/emaxx") 

pwkwd = "/feeds/lipper/emaxx" 

for item in os.listdir(pwkwd): # loop through items in dir
    if item.endswith(".zip"): # check for ".zip" extension
        file_name = os.path.abspath(item) # get full path of files
        fh = open(file_name, "rb")
        zip_ref = zipfile.ZipFile(fh)

        filelist = 'ISSUERS.TXT' , 'SECMAST.TXT' , 'FUND.TXT' , 'HOLDING.TXT'
        for name in filelist :
            try:
                outpath = "/SCRATCH/emaxx" + "/" + os.path.splitext(item)[0]
                zip_ref.extract(name, outpath)

            except KeyError:
                {}

        fh.close()

【问题讨论】:

  • 与..open 一起使用,然后你就不需要关心关闭文件了。我还建议使用 os.path.join 而不是连接字符串和路径
  • 顺便说一句,此代码仅在 pwkwd 是当前工作目录时才有效。否则 file_name = os.path.abspath(item) 不会建立正确的路径。您不需要绝对路径...os.path.join(pwkwd, item) 可以。
  • @Matt.St 感谢您的建议
  • @tdelaney 谢谢。 Pwkd 设置为我的 cwd。

标签: python zipfile


【解决方案1】:
import zipfile

zipdata = zipfile.ZipFile('somefile.zip')
zipinfos = zipdata.infolist()

# iterate through each file
for zipinfo in zipinfos:
    # This will do the renaming
    zipinfo.filename = do_something_to(zipinfo.filename)
    zipdata.extract(zipinfo)

参考: https://bitdrop.st0w.com/2010/07/23/python-extracting-a-file-from-a-zip-file-with-a-different-name/

【讨论】:

  • 这应该是正确答案:直接有效,无需后期处理。
【解决方案2】:

为什么不直接读取有问题的文件并自己保存而不是解压缩?比如:

import os
import zipfile

source_dir = "/feeds/lipper/emaxx"  # folder with zip files
target_dir = "/SCRATCH/emaxx"  # folder to save the extracted files

# Are you sure your files names are capitalized in your zip files?
filelist = ['ISSUERS.TXT', 'SECMAST.TXT', 'FUND.TXT', 'HOLDING.TXT']

for item in os.listdir(source_dir):  # loop through items in dir
    if item.endswith(".zip"):  # check for ".zip" extension
        file_path = os.path.join(source_dir, item)  # get zip file path
        with zipfile.ZipFile(file_path) as zf:  # open the zip file
            for target_file in filelist:  # loop through the list of files to extract
                if target_file in zf.namelist():  # check if the file exists in the archive
                    # generate the desired output name:
                    target_name = os.path.splitext(target_file)[0] + "_" + os.path.splitext(file_path)[0] + ".txt"
                    target_path = os.path.join(target_dir, target_name)  # output path
                    with open(target_path, "w") as f:  # open the output path for writing
                        f.write(zf.read(target_file))  # save the contents of the file in it
                # next file from the list...
    # next zip file...

【讨论】:

  • 感谢您的解决方案!
  • 对于文本文件,这个解决方案效果很好,但值得注意的是,对于混合文件,我们应该使用with open(target_path, "wb") as f:
  • Saikiran 的答案,它在提取之前简单地修改了 zipinfo,更简单、更直接并且可能更有效。
【解决方案3】:

您可以在提取每个文件后简单地运行重命名,对吗? os.rename 应该可以解决问题。

zip_ref.extract(name, outpath)
parent_zip = os.path.basename(os.path.dirname(outpath)) + ".zip"
new_file_name = os.path.splitext(os.path.basename(name))[0] # just the filename

new_name_path = os.path.dirname(outpath) + os.sep + new_file_name + "_" + parent_zip
os.rename(outpath, new_namepath)

对于文件名,如果您希望它是增量的,只需开始计数,然后对于每个文件,按 on 递增。

count = 0
for file in files:
    count += 1
    # ... Do our file actions
    new_file_name = original_file_name + "_" + str(count)
    # ...

或者,如果您不关心最终名称,则可以始终使用 uuid 之类的名称。

import uuid
random_name = uuid.uuid4()

【讨论】:

  • 感谢您的建议!
【解决方案4】:
outpath = '/SCRATCH/emaxx'
suffix = os.path.splitext(item)[0]

for name in filelist :
    index = zip_ref.namelist().find(name)
    if index != -1: # check the file exists in the zipfile
        filename, ext = os.path.splitext(name)
        zip_ref.filelist[index].filename = f'{filename}_{suffix}.{ext}' # rename the extracting file to the suffix file name
        zip_ref.extract(zip_ref.filelist[index], outpath) # use the renamed file descriptor to extract the file

【讨论】:

    【解决方案5】:

    我怀疑在提取过程中是否可以重命名文件。 提取文件后重命名文件怎么样?

    依靠linux bash,一行就可以实现:

    os.system("find "+outpath+" -name '*.txt' -exec echo mv {} `echo {} | sed s/.txt/"+zipName+".txt/` \;")
    

    所以,我们首先搜索指定文件夹中的所有txt文件,然后执行重命名命令,新名称由sed计算出来。

    代码未测试,我现在在 windows 上^^'

    【讨论】:

    • 非常感谢。对,使用 bash 总是一种出路:-)
    猜你喜欢
    • 1970-01-01
    • 2021-06-23
    • 2018-09-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多