forループの簡略化

forループの簡略化

以下のforループを理解して単純化したいと思います。たとえば、ディレクトリの各例のremファイルをリンクしたいとします。

文書:

file1.1.fq
file1.rem.1.fq
file1.2.fq
file1.rem.2.fq
file2.1.fq
file2.rem.1.fq
file2.2.fq
file2.rem.2.fq

forループ:

list=`for i in *rem*.1.fq; do echo $i | cut -f 1 -d \.; done`
for i in $list; do cat $i.rem.1.fq $i.rem.2.fq > $i.rem.b.fq; done

リストを作成せずにこれを実行できますか?機能は何ですかcut -f 1 -d?ファイル名の一部がリストの2つの部分の間にある場合は機能しますcat $i.rem.1.fqが、機能しないのはなぜですか?これは、以前のすべての項目(例:file1)をキャプチャするという意味ですか?cat $i.1.fqrem**rem*

答え1

努力する:

for i in *.rem.1.fq; do
    cat -- "$i" "${i%.1.fq}.2.fq" > "${i%.1.fq}.b.fq"
done

ファイルの存在確認を追加することもできます。

for i in *.rem.1.fq; do
    if [ -e "${i%.1.fq}.2.fq" ] && [ ! -e "${i%.1.fq}.b.fq" ]; then
        cat -- "$i" "${i%.1.fq}.2.fq" > "${i%.1.fq}.b.fq"
    fi
done

質問で提案されたアプローチはエラーが発生しやすいです。forファイルにスペースが含まれていると、2番目のループが正しく機能しない可能性があります。

cut -f 1 -d.文字列をフィールド(この場合は区切り.)に分割し、要求されたフィールド(この場合は最初のフィールドのみ)を出力します。文字列が与えられるとfile 1.whatever出力されますfile 1。繰り返しますが、globパターンがワイルドカード一致でファイル名を*rem*.1.fq返す可能性があることを考慮すると、エラーが発生しやすいです。anyremthing.1.fq*何もない(含む何もない)。

より良いオプションは、単一ループを実行し、引数拡張を使用することです。ループ内で代替形式を使用して、関連する名前を持つ他のファイルと一致させます。

  • 上記では、globパターンが使用されました*.rem.1.fq。さらに範囲を狭めることもできます。file[0-9].rem.1.fq
  • ${param%string}ループからサフィックスを削除するために使用されます.1.fq。多くのシェルは、他の種類のパラメータ拡張置換もサポートしています。${param/string/repl}

"$param"また、一般的にすべてを引用または置き換えることをお勧めします。それ以外の場合、ほとんどのシェルはフィールド分割とファイル名の生成を適用するため、代わりに"$(command)"試してみることができます。cat file 1cat 'file 1'

--ファイル名-

関連情報