Как объединить все файлы в другой папке в один файл и добавить новую строку

Как объединить все файлы в другой папке в один файл и добавить новую строку

У меня много папок и файлов, вот их структура

26-09-2016/CHANGELOG_20160926.TXT
26-09-2016/FILE_CHANGELOG_20160926.TXT
27-09-2016/CHANGELOG_20160927.TXT
27-09-2016/FILE_CHANGELOG_20160927.TXT

Мне нужен следующий вывод. Все файлы с именем типа CHANGELOG_*.TXTдолжны быть объединены и добавлена ​​отдельная новая строка в один файл типа CHANGELOG_20160926-20160930.TXT, и все файлы с именем типа FILE_CHANGELOG_*.TXTдолжны быть объединены и добавлена ​​отдельная новая строка в один файл тоже типа FILE_CHANGELOG_20160926-20160930.TXT.

Как мне это сделать?

решение1

Поскольку вы не указали никаких языковых требований, вот возможность использования Python 3.

#/usr/bin/env python3

from glob import glob
from os.path import basename
import re

for prefix in ('CHANGELOG', 'FILE_CHANGELOG'):
    files = dict((int(re.split('[_.]', basename(f))[-2]), f)
                 for f in glob('*-*-*/%s_*.TXT' % prefix))
    out_file = '%s_%d-%d.TXT' % (prefix, min(files.keys()), max(files.keys()))

    with open(out_file, 'w') as f_out:
        for date in sorted(files.keys()):
            with open(files[date]) as f_in:
                for line in f_in:
                    f_out.write(line)
            f_out.write("\n")

В основном он использует globи basenameдля перечисления и разбора имен файлов, сортируя их по дате. Минимальные/максимальные значения используются для построения выходного имени файла, и все файлы записываются туда по порядку. Не забудьте настроить шаблоны в соответствии с вашей фактической структурой каталогов, если это необходимо. Затем просто chmodзапустите:

$ chmod +x script.py
$ ./script.py

решение2

Решение вТХР:

Во-первых, давайте рассмотрим это как задачу обработки текста, предполагая, что у нас есть пример списка путей имен входного файла с именем paths. Мы преобразуем pathsв команды оболочки, которые catгруппируют файлы вместе и создают требуемые выходные файлы:

@(do
   (defstruct file-info nil
     full-name
     root-name
     date-key
     (:method equal (self) self.date-key)))
@(collect :vars (files))
@  (all)
@dd-@mm-@yyyy/@*{name}_@yyyy@[email protected]
@  (and)
@path
@  (end)
@  (bind files @(new file-info full-name path root-name name
                     date-key ^(,yyyy ,mm ,dd)))
@(end)
@(do
   (let ((h (group-by (usl root-name) files :equal-based)))
     [hash-update h sort]
     (dohash (name flist h)
       (let ((start (find-min flist))
             (end (find-max flist))
             (paths (mapcar (usl full-name) flist)))
         (put-line `cat @{paths " "} >\ \
                    @{start.root-name}_@{start.date-key ""}- \
                    @{end.date-key ""}.TXT`)))))

Бегать:

$ txr catfiles.txr paths
cat 26-09-2016/CHANGELOG_20160926.TXT 27-09-2016/CHANGELOG_20160927.TXT > CHANGELOG_20160926-20160927.TXT
cat 26-09-2016/FILE_CHANGELOG_20160926.TXT 27-09-2016/FILE_CHANGELOG_20160927.TXT > FILE_CHANGELOG_20160926-20160927.TXT

Для работы на реальных путях и выполнения catкоманд требуются простые модификации:

@(do
   (defstruct file-info nil
     full-name
     root-name
     date-key
     (:method equal (self) self.date-key)))
@(next :list (glob "*/*.TXT"))
@(collect :vars (files))
@  (all)
@dd-@mm-@yyyy/@*{name}_@yyyy@[email protected]
@  (and)
@path
@  (end)
@  (bind files @(new file-info full-name path root-name name
                     date-key ^(,yyyy ,mm ,dd)))
@(end)
@(do
   (let ((h (group-by (usl root-name) files :equal-based)))
     [hash-update h sort]
     (dohash (name flist h)
       (let ((start (find-min flist))
             (end (find-max flist))
             (paths (mapcar (usl full-name) flist)))
         (sh `cat @{paths " "} >\ \
              @{start.root-name}_@{start.date-key ""}- \
              @{end.date-key ""}.TXT`)))))

Единственными изменениями являются добавление a @(next :list (glob "*/*.TXT"))для перенаправления сканирования входных данных по списку путей, полученных из файловой системы, и переключение с put-stringна shдля catвыполнения команд.

Если списки файлов могут быть очень большими, мы столкнемся с ограничениями на передачу команд/argv ОС: мы не сможем объединить их в одну команду.

Возможным решением этой проблемы является изменение последней части кода на:

@(do
   (let ((h (group-by (usl root-name) files :equal-based)))
     (hash-update h (op sort))
     (dohash (name flist h)
       (let* ((start (find-min flist))
              (end (find-max flist))
              (paths (mapcar (usl full-name) flist))
              (target `@{start.root-name}_@{start.date-key ""}- \
                       @{end.date-key ""}.TXT`))
         (sh `> @target`)
         (each ((group-of-ten (tuples 10 paths)))
           (sh `cat @{group-of-ten " "} >> @target`))))))

То есть для каждого файла используйте , > fileчтобы убедиться, что он существует и обрезан до нуля. Затем используйте , cat ... >> fileчтобы добавить к нему журналы, группами по десять.

Связанный контент