私は数千のファイルを含むディレクトリにいますが、すべてのフィルターを適用するファイルの構文は次のとおりです:_*.imputed.*_info
_
Awkを使用して、データの5番目の列の値が0.50を超える各ファイルのレコードをフィルターで除外し、awk '{if($5 >= .5) {print}}' filename
を使用してそれを行うことができました。
それもうまくいきました。次に、500ほどのファイルすべてをループして、この基準に一致する各ファイルのレコードを連結しようとしました。
以下を試しましたが、構文が正しくありません。
_touch snplist.txt
for name in *.imputed.*_info; do
snps="awk '{if($5 >= .5) {print}}' $name"
cat snplist.txt "$snps" > snplist.txt
done
_
コードは各反復で出力ファイルを上書きします。また、実際にはawk
を呼び出しません。
やりたいことは
_awk '$5 >= 0.5' ./*.imputed.*_info >snplist.txt
_
これは、すべてのファイルを使用してawk
を一度に呼び出し、シェルが展開パターンを展開する順序で1つずつファイルを処理します。ファイルのいずれかの行の5番目の列が0.5以上の場合、その行は(_snplist.txt
_に)出力されます。これは、条件に関連付けられているアクション(_{...}
_ブロック)がない場合、デフォルトのアクションが現在の行を出力するために機能します。
大きなファイルの数(数千)がある場合、これは「引数リストが長すぎます」エラーを生成する可能性があります。その場合は、ループすることをお勧めします。
_for filename in ./*.imputed.*_info; do
awk '$5 >= 0.5' "$filename"
done >snplist.txt
_
awk
の結果を変数に格納する必要がないことに注意してください。ここでは、出力されただけで、ループ(したがって、ループ内のすべてのコマンド)が_snplist.txt
_にリダイレクトされます。
何千ものファイルの場合、awk
をファイルごとに個別に呼び出す必要があるため、これは非常に遅くなります。
スピードアップするために、awk
の1回の呼び出しではファイルが多すぎる場合は、次のようにxargs
の使用を検討してください。
_printf '%s\0' ./*.imputed.*_info | xargs -0 awk '$5 >= 0.5' >snplist.txt
_
これにより、printf
を使用してファイル名のリストが作成され、NUL終了リストとしてxargs
に渡されます。 xargs
ユーティリティはこれらを受け取り、awk
をできるだけ多くで一度にバッチで開始します。パイプライン全体の出力は_snplist.txt
_にリダイレクトされます。
このxargs
の代替案は、LinuxなどのUnixを使用していることを前提としています。これには、NUL終了入力を読み取るための非標準の_-0
_オプションを実装するxargs
コマンドがあります。また、_組み込みbash
ユーティリティ(printf
、OpenBSDのデフォルトのシェル)があるksh
のようなシェルを使用していることも前提としています。このような組み込みユーティリティがないため、ここでは機能しません)。
zsh
シェルの場合(つまり、bash
ではない):
_autoload -U zargs
zargs -- ./*.imputed.*_info -- awk '$5 >= 0.5' >snplist.txt
_
これはzargs
を使用します。これは、基本的にxargs
をロード可能なzsh
シェル関数として再実装したものです。詳細については、_zargs --help
_(関数のロード後)およびzshcontrib(1)
マニュアルを参照してください。
これを行うだけです:
awk '$5 >= .5' *.imputed.*_info > snplist.txt
私はこのようなことのためにfind
を使う習慣があります。
find . -type f -name "*.imputed.*_info" -exec awk '$5 >= 0.5' {} \; > ./snplist.txt