在目录中迭代使用python压缩文件

时间:2011-05-06 19:24:49

标签: python loops

我需要遍历一个文件夹,找到文件名相同的每个实例(扩展名除外),然后将每个文件压缩(最好使用tarfile)到一个文件中。

所以我有5个名为“example1”的文件,每个文件都有不同的文件扩展名。我需要将它们拼接在一起并输出为“example1.tar”或类似的东西。

使用简单的for循环就足够了,例如:

  

tar = tarfile.open('example1.tar',“w”)

     
    

表示glob('example1 *')中的输出:

         
      

tar.add(输出)

             
        

tar.close()

      
    
  

但是,有300个“示例”文件,我需要遍历每个文件及其相关的5个文件才能使其工作。这是我的头脑。任何建议都非常感谢。

6 个答案:

答案 0 :(得分:2)

你可以这样做:

  • 列出目录中的所有文件
  • 创建一个字典,其中basename是键,所有扩展名都是值
  • 然后按字典键
  • tar所有文件

这样的事情:

import os
import tarfile
from collections import defaultdict

myfiles = os.listdir(".")   # List of all files
totar = defaultdict(list)

# now fill the defaultdict with entries; basename as keys, extensions as values
for name in myfiles:
    base, ext = os.path.splitext(name)
    totar[base].append(ext)

# iterate through all the basenames
for base in totar:
    files = [base+ext for ext in totar[base]]
    # now tar all the files in the list "files"
    tar = tarfile.open(base+".tar", "w")
    for item in files:    
        tar.add(item)
    tar.close()

答案 1 :(得分:2)

您所描述的模式概括为MapReduce。我在网上找到了a simple implementation MapReduce,其中更简单的版本是:

def map_reduce(data, mapper, reducer):
    d = {}
    for elem in data:
        key, value = mapper(elem)
        d.setdefault(key, []).append(value)
    for key, grp in d.items():
        d[key] = reducer(key, grp)
    return d

您希望按照名称对所有文件进行分组,而不使用扩展名,您可以从os.path.splitext(fname)[0]获取该扩展名。然后,您希望使用tarfile模块从每个组中创建一个tarball。在代码中,即:

import os
import tarfile

def make_tar(basename, files):
    tar = tarfile.open(basename + '.tar', 'w')
    for f in files:
        tar.add(f)
    tar.close()

map_reduce(os.listdir('.'),
           lambda x: (os.path.splitext(x)[0], x),
           make_tar)

编辑:如果要以不同方式对文件进行分组,只需将第二个参数修改为map_reduce即可。上面的代码对表达式os.path.splitext(x)[0]具有相同值的文件进行分组。因此,要将基本文件名与所有分开的扩展名分组,您可以将该表达式替换为strip_all_ext(x)并添加:

def strip_all_ext(path):
    head, tail = os.path.split(path)
    basename = tail.split(os.extsep)[0]
    return os.path.join(head, basename)

答案 2 :(得分:1)

你必须遇到问题。单独解决。

  1. 查找匹配的名称。使用collections.defaultict

  2. 找到匹配的名称后创建tar文件。你已经很好地覆盖了它。

  3. 因此。首先解决问题1。

    使用glob获取所有名称。使用os.path.basename拆分路径和基本名称。使用os.path.splitext拆分名称和扩展名。

    列表字典可用于保存所有具有相同名称的文件。

    这就是你在第1部分中所做的事情吗?


    第2部分将文件放入tar档案中。为此,您已经拥有了所需的大部分代码。

答案 3 :(得分:0)

尝试使用glob模块:http://docs.python.org/library/glob.html

答案 4 :(得分:0)

#! /usr/bin/env python

import os
import tarfile

tarfiles = {}
for f in os.listdir ('files'):
    prefix = f [:f.rfind ('.') ]
    if prefix in tarfiles: tarfiles [prefix] += [f]
    else: tarfiles [prefix] = [f]

for k, v in tarfiles.items ():
    tf = tarfile.open ('%s.tar.gz' % k, 'w:gz')
    for f in v: tf.addfile (tarfile.TarInfo (f), file ('files/%s' % f) )
    tf.close ()

答案 5 :(得分:-1)

import os
import tarfile

allfiles = {}

for filename in os.listdir("."):
    basename = '.'.join (filename.split(".")[:-1] )
    if not basename in all_files:
        allfiles[basename] = [filename]
    else:
        allfiles[basename].append(filename)

for basename, filenames in allfiles.items():
    if len(filenames) < 2:
        continue
    tardata = tarfile.open(basename+".tar", "w")
    for filename in filenames:
        tardata.add(filename)
    tardata.close()