res.1
±10,000個のファイル( - )があり、res.10000
すべて1つの列と同じ数の行で構成されています。私が望むのは本質的に簡単です。すべてのファイルを列単位で新しいファイルにマージしますfinal.res
。私は以下を試してみました。
paste res.*
しかし、(これは結果ファイルの小さなサブセットに対して機能するようですが、コレクション全体で実行すると、次のエラーが発生しますToo many open files
。
これを達成するための「簡単な」方法が必要です。しかし残念ながら、私はUnixに初めて接する人です。よろしくお願いします!
PS:(私)データファイルの1つがどのように見えるかについてのアイデアを提供するには:
0.5
0.5
0.03825
0.5
10211.0457
10227.8469
-5102.5228
0.0742
3.0944
...
答え1
マシンへのルートアクセス権がある場合は、開いているファイルディスクリプタの最大数の制限を一時的に増やすことができます。
ulimit -Hn 10240 # The hard limit
ulimit -Sn 10240 # The soft limit
それから
paste res.* >final.res
後で元の値にリセットできます。
ㅏ2番目の解決策、制限を変更できない場合:
for f in res.*; do cat final.res | paste - $f >temp; cp temp final.res; done; rm temp
ファイルごとに1回呼び出され、paste
すべての列を含む巨大なファイルが生成されます(1分かかります)。
編集する:猫に役に立たない用途...いいえ!
コメントで述べたように、cat
ここで()を使用することはcat final.res | paste - $f >temp
役に立ちません。ループを初めて実行すると、ファイルはfinal.res
まだ存在しません。paste
その後、失敗し、ファイルがいっぱいにならず、生成されません。私の解決策はcat
初めてのみ失敗No such file or directory
し、paste
標準入力から空のファイルを読み込みますが、続きます。このエラーは無視できます。
答え2
もし錯乱'答えが適用されない場合(必須権限がないため)、paste
次のように一括呼び出しできます。
ls -1 res.* | split -l 1000 -d - lists
for list in lists*; do paste $(cat $list) > merge${list##lists}; done
paste merge* > final.res
今回は、etcというファイルに含まれている1000個のファイルが一覧表示され、そのファイルがlists00
etclists01
というres.
ファイルに貼り付けられ、最後merge00
に部分的merge01
にマージされた結果ファイルがすべてマージされます。
言ったように錯乱一度に使用するファイルの数を増やすことができます。制限は、指定された値からulimit -n
開いているファイルの数を引いたものです。
ls -1 res.* | split -l $(($(ulimit -n)-10)) -d - lists
使用制限から10ポイント割引されます。
あなたのバージョンがsplit
それをサポートしていない場合は-d
削除できます。split
数字のサフィックスを使用するように求められます。デフォルトではaa
、サフィックスは背の代わりに背にab
なります01
。02
ファイルが多すぎて失敗する場合ls -1 res.*
(「パラメータリストが多すぎます」)、次のように置き換えることができますfind
。
find . -maxdepth 1 -type f -name res.\* | split -l 1000 -d - lists
(示したようにドンクリスティ、出力をパイピングするときは必要ありませんが、-1
エイリアスの場合を処理ls
するためにそのままにしてください。 )ls
-C
答え3
次のように実行してみてください。
ls res.*|xargs paste >final.res
バッチを複数の部分に分割し、次のことを試すこともできます。
paste `echo res.{1..100}` >final.100
paste `echo res.{101..200}` >final.200
...
最後に、最終ファイルをマージします。
paste final.* >final.res
答え4
関連ファイルの数、行サイズなどを考慮すると、ツールのデフォルトサイズ(awk、sed、貼り付け、*など)を超えると思います。
このために、10,000個のファイルや数十万行(それぞれ10行の10,000個のファイル(例では行の最大サイズ))を開かない小さなプログラムを作成します。各ファイルから読み取られたバイト数を格納するには、約10,000個の整数配列のみが必要です。欠点は、ファイル記述子が1つだけあり、ファイルごとに1行あたりに再利用されるため、速度が遅くなる可能性があることです。
FILES
との定義はROWS
実際の正確な値に変更する必要があります。出力は標準出力に送信されます。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define FILES 10000 /* number of files */
#define ROWS 500 /* number of rows */
int main() {
int positions[FILES + 1];
FILE *file;
int r, f;
char filename[100];
size_t linesize = 100;
char *line = (char *) malloc(linesize * sizeof(char));
for (f = 1; f <= FILES; positions[f++] = 0); /* sets the initial positions to zero */
for (r = 1; r <= ROWS; ++r) {
for (f = 1; f <= FILES; ++f) {
sprintf(filename, "res.%d", f); /* creates the name of the current file */
file = fopen(filename, "r"); /* opens the current file */
fseek(file, positions[f], SEEK_SET); /* set position from the saved one */
positions[f] += getline(&line, &linesize, file); /* reads line and saves the new position */
line[strlen(line) - 1] = 0; /* removes the newline */
printf("%s ", line); /* prints in the standard ouput, and a single space */
fclose(file); /* closes the current file */
}
printf("\n"); /* after getting the line from each file, prints a new line to standard output */
}
}