2011-05-06 72 views
3

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

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

这将是一个简单的for循环如很容易:

焦油= tarfile.open( 'example1.tar', “W”)

在水珠输出( '例1 *'):

tar.add(输出)

tar.clo SE()

然而,有300个“榜样”的文件,我需要通过每一个及其相关的5个文件,以使这项工作进行迭代。这是我的头。任何建议不胜感激。

回答

2

您描述的模式概括为MapReduce。我发现的MapReduce a simple implementation网上,从偶数简单的版本是:

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) 
+0

无论如何改变这个代码或使用os.path.extsep为了从一个文件拆分多个扩展。例如'foobar.aux.xml' – KennyC 2011-05-08 22:22:25

+0

@KennyC:更新回答 – Karmastan 2011-05-08 22:56:50

+0

@Karamastan:完美!连续的工作。谢谢 – KennyC 2011-05-09 14:43:22

1

你得问题。分开解决。

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

  2. 找到匹配的名称后创建tar文件。你有很好的覆盖。

所以,首先解决问题1。使用glob获得所有的名字。使用os.path.basename拆分路径和基本名称。使用os.path.splitext来拆分名称和扩展名。

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

这就是你在做的第1部分?


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

2

你可以这样做:

  • 列入目录
  • 创建一个字典,其中的基本部分是关键,所有分机都值
  • 然后焦油字典键中的所有文件中的所有文件

事情是这样的:

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() 
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() 
+0

下面是完整的脚本: – Hyperboreus 2011-05-06 19:46:34

+0

@Hyperboreus:-1 ...'˚F ='fubar';前缀= f [:f.rfind('。')]'产生''fuba'' ...使用'os.path.splitext()' – 2011-05-06 21:52:01

+0

@Hyboreus:当你在它的时候, ['在切片和字典访问和'('在函数调用 – 2011-05-06 21:57:02

-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() 
+0

-1'使用os.path.splitext ()' - ''。'。join('fubar'.split(“。”)[: - 1])'产生一个空字符串。 – 2011-05-07 07:24:48