一連のフォルダに一連のファイルがあります。たとえば、次のようになります。
~/BR2_1-3/bin.1.permissive.tsv
~/BR2_1-3/bin.2.permissive.tsv
~/BR2_1-3/bin.3.orig.tsv
~/BR2_2-4/bin.1.strict.tsv
~/BR2_2-4/bin.2.orig.tsv
~/BR2_2-4/bin.3.permissive.tsv
~/BR2_2-4/bin.4.permissive.tsv
~/BR2_3-5/bin.1.permissive.tsv
~/BR2_3-5/bin.2.permissive.tsv
~/BR2_3-5/bin.3.orig.tsv
~/BR2_3-5/bin.4.orig.tsv
~/BR2_3-5/bin.5.permissive.tsv
...
私が望むのは、各* .tsvファイルから最初と5番目の列を抽出し、そのフォルダにタブで区切られた新しいファイルを作成することです。以下を使用して、そのフォルダの下の各ファイルに対して個別にこれを実行できます。
$ awk -F '\t' 'OFS="\t" {if ($5 != "") print($1,$5)}' bin.1.permissive.tsv > test
$ sed -i '1d' test
$ mv test BR2_1-bin.1.permissive.ec
私の質問はこれらのファイルが100個以上あるので、for
端末でこの手順を自動的に実行するようにループを作成する方法はありますか?です。
フォルダとファイルの命名規則は次のとおりです。フォルダは「BR(2~5)_(1~6)-(n, フォルダに含まれるファイル数)」です。 /許可/オリジナル).tsv”。
入力ファイルは出力ファイルにマップする必要があります。対応する入力ファイルが「~/BR2_1-3/bin.1.permissive.tsv」の場合、出力ファイル名は「BR2_1-bin.1.permissive.ec」です。対応する入力ファイルが「~/BR2_3-5/bin.3.orig.tsv」の場合、出力ファイル名は「BR2_3-bin.3.orig.ec」です。また、出力ファイルは対応する入力ファイルと同じフォルダに書き込む必要があります。コメントでこんな質問をしてくれてありがとう。
事前に感謝し、すべての提案を歓迎します!
答え1
find
通常、xargs
次のことをお勧めします。
find "$HOME" -name \*.tsv |
xargs awk -F'\t' -v OFS='\t' '$5 != "" {print $1, $5}' >> output.tsv
またはもっと安全に
find "$HOME" -name \*.tsv -print0 |
xargs -0 awk -F'\t' -v OFS='\t' '$5 != "" {print $1, $5}' >> output.tsv
find-print0
コマンドはヌルバイトで区切られた一致ファイルを印刷し、xargs-0
オプションはヌルバイトを使用してファイル名を区切ります。これは、ファイル名にヌルバイトが許可されず、改行文字が有効な文字であるために行われます。
いいですね。各ファイルはそのファイル.ec
として処理する必要があります。
find "$HOME" -name \*.tsv -print0 |
xargs -0 awk -F '\t' -v OFS='\t' '
FNR == 1 {
if (ec) close(ec)
ec = gensub(/\.tsv$/, ".ec", 1, FILENAME)
next
}
$5 != "" {print $1, $5 > ec}
'
メモ:
print ... > ex
- シェルのリダイレクトと同様に、出力を変数に含まれるファイル名にリダイレクトしますec
。- シェルとは異なり、これは「印刷」ごとにファイルを上書きしませんが、最初の印刷のみがファイルを切り捨てたり作成したり、後続の印刷はすべてファイルに追加されます。
close
「開いているファイルが多すぎます」というエラーが発生する可能性があるため、ファイルの使用が終了するまで待ってから開くのが最善です。- ファイルの最初のレコードにあるときにこれを行います。
- 変数が空でない場合は、
ec
次の期間保存されます。より早い処理されたファイル
gensub
sub
と同様のgawk固有の機能ですgsub
。それマニュアルに記載されているsub
とは異なりますgsub
。gensub
返品変換された値です。