Итерация в каталоге для архивирования файлов с помощью Python - PullRequest
3 голосов
/ 06 мая 2011

Мне нужно перебрать папку и найти каждый экземпляр, где имена файлов идентичны (за исключением расширения), а затем сжать (желательно используя tarfile) каждое из них в один файл.

Итак, у меня есть 5 файловnamed: "example1", каждый с разными расширениями.Мне нужно сжать их вместе и вывести их как «example1.tar» или что-то подобное.

Это было бы достаточно просто с помощью простого цикла for, такого как:

tar = tarfile.open ('example1.tar', "w")

для вывода в глобальном формате ('example1 *'):

tar.add (вывод)

tar.close ()

однако есть 300 «примеров» файлов, и мне нужно перебрать каждый из них и связанные с ними 5 файлов, чтобы сделать эту работу.Это над моей головой.Любой совет с благодарностью.

Ответы [ 6 ]

2 голосов
/ 07 мая 2011

Шаблон, который вы описываете, обобщает для MapReduce. Я нашел простую реализацию 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. В коде это:

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 голосов
/ 06 мая 2011

Вы можете сделать это:

  • перечислить все файлы в каталоге
  • создать словарь, в котором базовое имя является ключом, а все расширения являются значениями
  • затем 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 голос
/ 06 мая 2011

У тебя проблемы.Решите отдельно.

  1. Поиск подходящих имен.Используйте collections.defaultict

  2. Создание файлов tar после того, как вы найдете подходящие имена.У вас это достаточно хорошо освещено.

Итак.Сначала решите проблему 1.

Используйте glob, чтобы получить все имена.Используйте os.path.basename, чтобы разделить путь и базовое имя.Используйте os.path.splitext, чтобы разделить имя и расширение.

Словарь списков может использоваться для сохранения всех файлов с одинаковым именем.

Это то, что вы делаете в части 1?


Часть 2 помещает файлы в архивы tar.Для этого у вас есть большая часть кода, который вам нужен.

0 голосов
/ 06 мая 2011
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 голосов
/ 06 мая 2011
#! /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 голосов
/ 06 мая 2011

Попробуйте использовать модуль glob: http://docs.python.org/library/glob.html

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...