2

1つのフォルダに何億もの小さなプレーンテキストファイルがあります。いくつかの処理を行って、それらを1つの大きなファイルにマージしたいと思います。それを行うための最速の方法は何ですか?現在、私は次のコードを持っています:


#!/bin/bash
FOLDER="some-folder"
TARGET="target-file"
FILES=`find $FOLDER -name "*.txt"`
for f in $FILES
  do
    cat $f | ./some-processing-script.pl >> $TARGET
  done

これは少数のファイルに対してはうまく機能しますが。大量のファイルを実際に処理するために使用する場合、ターゲットファイルが25G程度を超えると、非常に遅くなります。cat ... >> $TARGETこれは、ターゲットの最後に新しいコンテンツを添付する前に、新しい入力ファイルごとに現在のターゲットファイル全体をスキャンする必要があるためだと思います。

私はこれを解決するためにJavaまたはPythonを使用する方法を知っています。これをbashで解決できるかどうかだけ知りたいです。ありがとう。

4

5 に答える 5

5

代わりに、ループの出力をリダイレクトできます。

for f in $FILES
  do
    ./some-processing-script.pl < $f
  done >> $TARGET

(猫の無駄な使用も排除しました。)

于 2012-11-10T06:35:28.423 に答える
4

「マージ」の定義は何ですか?Perlスクリプトはファイル名の引数を取りますか?ファイル名にスペースやその他の厄介な文字が含まれていることはありますか?

スクリプトがコマンドライン引数を受け取らないと仮定すると、次のいずれかを実行できます。

cat $(find $FOLDER -name "*.txt") | ./some-processing-script.pl >$TARGET

または、1つのコマンドラインに対してファイルが多すぎる場合は、次のようにします。

find $FOLDER -name "*.txt" -print | xargs cat | ./some-processing-script.pl > $TARGET

または、名前にスペースがあり、十分に現代的である場合find(POSIX 2008準拠):

find $FOLDER -name "*.txt" -exec cat {} + | ./some-processing-script.pl > $TARGET

本当に常にターゲットファイルに追加したい場合は、をに置き換え>>>ください。これらの例でcatは、は複数のファイルを連結するために使用されています。これは、の適切な使用法ですcat。UUOC(Useless Use of cat)賞はcat、I / Oリダイレクトが代わりに仕事をするときに、一度に1つのファイルを処理するために使用することになります。

Perlスクリプトを担当している場合は、「標準フィルター」、つまりコマンドラインで指定されたファイルを読み取るプログラム、またはファイルが指定されていない場合は標準入力になるように変更する必要があります。cat次に、 :を削除できます。

 ./some-processing-script.pl $(find $FOLDER -name "*.txt") >$TARGET

find $FOLDER -name "*.txt" -print | xargs ./some-processing-script.pl > $TARGET

find $FOLDER -name "*.txt" -exec ./some-processing-script.pl {} + > $TARGET

これらのオプションのうち、最後のものは、Perlスクリプトがコマンドラインでファイル名を受け入れるか、受け入れるように変更できると仮定して、私が使用するオプションです。Perlスクリプトがコマンドライン引数を処理できない(実行されない)場合は、catandパイプを使用して3番目のコマンドを使用します。しかし、これは、可能な場合に標準のUnixフィルターのように動作するようにプログラム(Perlスクリプト)を設計する必要がある理由を示しています。つまり、それらをより効率的にコマンドパイプラインに組み合わせることができます。

于 2012-11-10T06:36:38.637 に答える
0

スクリプトを変更できる場合はperl、次を使用することをお勧めします。

shopt -s globstar # enable bash4 recursion with **
./some-processing-script.pl **/*.txt > big_file.txt

perlスクリプト:

while (<>) {
    # processing the content
    print;
}

あなたもできる:

find $FOLDER -name "*.txt" -exec cat {} + |
    ./some-processing-script.pl > big_file.txt
于 2012-11-10T20:56:50.160 に答える