
我想將數千個小文本文件合併為一個大文本文件。我將它們放在結構如下的目錄中:timestamp1/status.txt
。例如:20130430133144/status.txt
。到目前為止,我知道
cat */* > bigtextfile.txt
適用於少量文件。但它適用於更高的數字嗎?我想知道是否cat
要收集所有文件的內容,然後嘗試保存到bigtextfile
.否則,我想必須有另一種方法來做到這一點,例如獲取一個文件,將其附加到bigtextfile
,然後獲取另一個文件,依此類推。
答案1
在:
cat */* > bigtextfile.txt
shell 將擴展*/*
到(非隱藏)匹配檔案的排序列表,並將cat
使用這些檔案路徑作為參數執行。
cat
將依序開啟每個文件並將從文件中讀取的內容寫入其標準輸出。cat
記憶體中一次不會容納多個充滿資料的緩衝區(大約幾千位元組)。
但您可能會遇到的一個問題是,參數列表cat
太大,以至於達到了execve()
系統呼叫參數大小的限制。因此,您可能需要拆分該文件列表並運行cat
多次。
您可以使用xargs
它(這裡使用 GNU 或 BSDxargs
作為非標準-r
和-0
選項):
printf '%s\0' */* | xargs -r0 cat -- > big-file.txt
(因為printf
是內建在shell中的,所以不經過系統execve
調用,所以沒有經過它的限制)。
或find
建立文件列表並根據需要運行盡可能多的 cat 命令:
find . -mindepth 2 -maxdepth 2 -type f -exec cat {} + > big-file.txt
或便攜式:
find . -path './*/*' -prune -type f -exec cat {} + > big-file.txt
(請注意,與 相反*/*
,它將包含隱藏文件(以及隱藏目錄中的文件),而不是在目錄的符號鏈接中查找文件,並且文件列表不會被排序)。
如果在最新版本的 Linux 上,您可以透過執行下列操作來取消參數大小的限制:
ulimit -s unlimited
cat -- */* > big-file.txt
透過zsh
,您也可以使用zargs
:
autoload zargs
zargs -- */* -- cat > big-file.txt
透過ksh93
,您可以使用command -x
:
command -x cat -- */* > big-file.txt
所有這些都執行相同的操作,拆分文件列表並cat
根據需要運行盡可能多的命令。
再次,您可以使用內建命令來ksh93
繞過限制:execve()
cat
command /opt/ast/bin/cat -- */* > big-file.txt
答案2
Nocat
在開始寫出之前不會緩衝所有檔案。
但是,如果您有大量文件,則可能會遇到傳遞給 的參數數量問題cat
。預設情況下,linux 核心只允許將固定數量的參數傳遞給任何程式(我不記得如何取得該值,但大多數情況下是數千個)。
要解決這個問題,你可以這樣做:
find -mindepth 2 -maxdepth 2 -type f -exec cat {} \; > bigtextfile.txt
這基本上將cat
分別調用 . 找到的每個檔案find
。
答案3
如果文件數量太大,*/*
將給出太大的參數列表。如果是這樣,則可以執行以下操作:
find . -name "*.txt" | xargs cat > outfile
(這個想法是使用find
來獲取文件名,並將它們放入一個流中;xargs
將該流分成可管理的部分以提供給cat
,它將它們連接到 的輸出流中xargs
,然後進入outfile
)。