次の問題を解決するために誰が助けることができますか?私は異なる種に対して約40のディレクトリを持ち、各ディレクトリには異種配列を含む100の配列ファイルがあります。各種カタログのシーケンスファイルは同様の方法で命名されます。 40種類のディレクトリにある同じ名前のファイルを同じ名前のシーケンスファイルにリンクしたいと思います。
たとえば、「Species1」、「Species2」、「Species3」という3つのディレクトリがあります。これらのディレクトリには、「SequenceA.fasta」、「SequenceB.fasta」、「SequenceC.fasta」などの類似した名前のファイルが含まれています。別のSequenceA.fastaファイルのすべての内容を別のディレクトリの「SequenceA.fasta」という新しいファイルにリンクする必要があります。どうすればいいですか?
下のループで試しましたが失敗しました。ファイルが作成されましたが空です。
ls . | while read FILE; do cat ./*/"$FILE" >> ./final/"$FILE"; done
アドバイスや助けてくれてありがとう!
(クロスポストの可能性があり、申し訳ありません。以前に誤ってフォーラムにこの質問を投稿しました。)
答え1
この回答にはいくつかの注意事項があります。
ls
glob
シェルモードを使用して目的の操作を実行できる場合は、出力を解析するのは一般的に悪い考えです。http://mywiki.wooledge.org/ParsingLs]。移植性のためにnullglobシェルオプションを使用しませんが、これはスクリプトを少し短くします。グローバルパターンが広すぎないことを確認するために、
cat
入力と出力に同じファイル名を使用するように指示します。これにより、無限のサイズのファイルを作成しようとすると、ハードドライブが非常に迅速にいっぱいになります。同様のパターンを提供しても
*.fasta
ファイルと一致しない場合は、*.fasta
リテラル文字列を使用してください。というファイルがある場合は、
*.fasta
ファイルとパターンの違いを区別する1つの方法は、読み取り可能であることを確認することです。--
悪意のあるファイル名の可能性がある場合は、パラメータの解析を終了することをお勧めします。
まず簡単なスクリプトです。
# Simple script, assumes that "Species1" has all the needed "SequenceX.fasta" files
# Start in the directory containing "Species1", "Species2" etc.
# create output directory
mkdir "final"
# Go into the first directory
cd "Species1"
# Loop over all the files
for i in *".fasta"
do
# join all the like named files in the sibling directories to the output
# use a pattern which doesn't match ../final/$i to get list of files to join.
cat "../Species"*"/$i" > "../final/$i"
done
これは、「Species1」にすべての「SequenceX.fasta」ファイルがあると仮定します。そうでない場合は、二重ループが必要な場合があります。これはより強力ですが、より長く遅いです。
# Start in the top level and loop over the directories
for dir in */
do
# don't do anything inn the output directory
[ "$dir" = "final" ] && continue
# cd into directory, protecting against rogue directory names
cd "./$dir" || { echo "cd to $dir failed" >&2 ; exit 1 ; }
# loop over the files
for file in *"fasta"
do
# check the file exists, if there are no files matching the pattern
# then the shell will pass the pattern through to the loop
if [ -r "$file" ] ; then
cat -- "$file" >> "../final/$file"
fi
done
cd ".." || { echo "failed to return from $dir" ; exit 1 ; }
done