6

私は、自分が書いたスクリプトをより単純なものにしようとしてきました。

フォルダー内のすべてのファイル、またはフォルダーのサブディレクトリのすべてのファイルの単語数を取得する方法は多数あります。

たとえば、私は書くことができます

wc */* 

次のような出力が得られる可能性があります (これが目的の出力です)。

   0        0        0 10.53400000/YRI.GS000018623.NONSENSE.vcf
   0        0        0 10.53400000/YRI.GS000018623.NONSTOP.vcf
   0        0        0 10.53400000/YRI.GS000018623.PFAM.vcf
   0        0        0 10.53400000/YRI.GS000018623.SPAN.vcf
   0        0        0 10.53400000/YRI.GS000018623.SVLEN.vcf
   2       20      624 10.53400000/YRI.GS000018623.SVTYPE.vcf
   2       20      676 10.53400000/YRI.GS000018623.SYNONYMOUS.vcf
  13      130     4435 10.53400000/YRI.GS000018623.TSS-UPSTREAM.vcf
 425     4250   126381 10.53400000/YRI.GS000018623.UNKNOWN-INC.vcf

ただし、ファイルが多すぎると、次のようなエラー メッセージが表示されることがあります。

-bash: /usr/bin/wc: Argument list too long

そのため、変数を作成して、次のように一度に 1 つのフォルダーを実行できます。

while read $FOLDER
do
    wc $FOLDER/* >> outfile.txt
done < "$FOLDER_LIST"

このように 1 行から 5 行になります。

さらに、あるケースでは、grep -v最初に使用してから、次のように単語カウントを実行します。

grep -v dbsnp */* | wc

しかし、これには次の 2 つのエラーが発生します。

  1. 引数リストが長すぎます
  2. 長すぎなければ、ファイルごとではなく、一度にすべてのファイルの wc が表示されます。

要約すると、私はこれができるようになりたいです:

grep -v dbsnp */* wc > Outfile.txt
awk '{print $4,$1} Outfile.txt > Outfile.summary.txt

上記のように出力を返すようにします。

これを行う非常に簡単な方法はありますか?または、少なくともループを見ていますか?繰り返しますが、私は他の人と同じように 4 ~ 10 行のスクリプトを使用してこれを行う 101 通りの方法を知っていますが、コマンド プロンプトに 2 つのワンライナーを入力するだけで済むようにしたいと思っています...そしてシェルに関する私の知識は私がOSに求めていることをどの方法で許可するかを知るにはまだ十分ではありません。

編集 -

解決策が提案されました:

find -exec grep -v dbsnp {} \; | xargs -n 1 wc

このソリューションは、次の出力につながります。

wc: 1|0:53458644:AMBIGUOUS:CCAGGGC|-16&GCCAGGGCCAGGGC|-18&GCCAGGGCC|-19&GGCCAGGGC|-19&GCCAGGGCG|-19,.:48:48,48:4,4:0,17:-48,0,-48:0,0,-17:27:3,24:24: No such file or directory
wc: 10: No such file or directory
wc: 53460829: No such file or directory
wc: .: Is a directory
      0       0       0 .
wc: AA: No such file or directory
wc: CT: No such file or directory
wc: .: Is a directory
      0       0       0 .
wc: .: Is a directory
      0       0       0 .

私が知る限り、各行をファイルとして扱っているようです。私はまだ他の回答を見直しています。あなたの助けに感謝します。

4

4 に答える 4

2

に一致するものが多すぎる*/*ため、grep は長い引数リストを受け取ります。findこれを回避するために使用できます。

find -exec grep -v dbsnp {} \; | wc

また、可能性のあるトラバーサル エラーも取り除きたい場合があります。

find -exec grep -v dbsnp {} \; 2> /dev/null | wc
于 2014-06-05T06:20:12.333 に答える
0

perreal の回答に基づく:

wcファイルごとに必要な場合は、次を使用できますxargs

find -exec grep -v dbsnp {} \; | xargs -n 1 wc

xargs標準入力を読み取り、それを使用してコマンドラインを構築および実行できます。したがって、入力ストリームの結果を読み取り、wc単一のアイテム ( ) ごとに実行します-n 1

于 2014-06-05T06:55:12.867 に答える
0

これは私のために働く:

grep -or "[a-zA-Z]*" * | cut -d":" -f2 | sort | uniq -c

あなたが探しているのは MapReduce アルゴリズムですhttp://en.wikipedia.org/wiki/MapReduce

于 2014-06-05T06:39:43.930 に答える