何千もの小さなテキストファイルを1つの大きなテキストファイルにマージしたいです。私はそれらを次の構造のディレクトリに入れましたtimestamp1/status.txt
:たとえば: 20130430133144/status.txt
。これまで私は知っています
cat */* > bigtextfile.txt
少数のファイルに適しています。しかし、より高い数字でも動作しますか?cat
すべてのファイルの内容を収集してから保存しようとしているかどうか疑問に思います。そうでない場合は、ファイルをインポートして追加し、別のファイルをインポートするbigtextfile
などの他の方法が必要です。bigtextfile
などのたとえ話。
答え1
存在する:
cat */* > bigtextfile.txt
シェルは*/*
(非表示の)一致するファイルのソートされたリストに展開され、cat
これらのファイルパスを引数として使用して実行されます。
cat
各ファイルは順番に開き、ファイルから読み取った内容が標準出力に書き込まれます。cat
一度にメモリに保持されるデータでいっぱいのバッファ(数キロバイト程度)は、2つ以上ありません。
ただし、発生する可能性のある問題の1つは、パラメータのリストが大きすぎてcat
システムコールのexecve()
パラメータサイズ制限に達することです。したがって、ファイルのリストを分割してcat
複数回実行する必要があるかもしれません。
これを使用できますxargs
(ここではGNUまたはBSDをxargs
非標準-r
および-0
オプションとして使用)。
printf '%s\0' */* | xargs -r0 cat -- > big-file.txt
(printf
シェルに内蔵されているためシステムコールを経ないので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
Pass 以下をksh93
使用できますcommand -x
。
command -x cat -- */* > big-file.txt
これらはすべて同じことを行い、ファイルのリストを分割し、必要なだけcat
多くのコマンドを実行します。
今回も組み込みコマンドを使用してksh93
制限を解決できます。execve()
cat
command /opt/ast/bin/cat -- */* > big-file.txt
答え2
いいえは、cat
書き込みを開始する前にすべてのファイルをバッファリングしません。
ただし、ファイル数が多いと、渡された引数の数に問題が発生する可能性があります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