以下の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.fq
rem
*
*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 1
cat 'file 1'
--
ファイル名-
。