如何將其他資料夾中的所有檔案合併為一個檔案並新增換行符

如何將其他資料夾中的所有檔案合併為一個檔案並新增換行符

我有很多資料夾和文件,這是我的結構

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")

它基本上使用globbasename來列出和解析文件名,並按日期對它們進行排序。最小/最大值用於建立輸出檔案名,所有檔案都按順序寫入其中。如果有必要,不要忘記將模式調整為實際的目錄結構。然後,chmod運行:

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

答案2

解決方案在TXR:

首先,我們將其視為文字處理任務,假設我們有路徑名範例清單和名為 的輸入檔paths。我們將檔案組轉換paths為 shell 命令並產生所需的輸出檔案: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-stringshcat

如果檔案清單可能非常大,我們將遇到作業系統命令/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將日誌以十個為一組附加到其中。

相關內容