將大量文字檔案合併為一個大文字文件

將大量文字檔案合併為一個大文字文件

我想將數千個小文本文件合併為一個大文本文件。我將它們放在結構如下的目錄中: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)。

相關內容