Может ли кто-нибудь помочь мне со следующей проблемой? У меня есть около 40 каталогов разных видов, каждый с сотнями файлов последовательностей, которые содержат ортологичные последовательности. Файлы последовательностей имеют одинаковые имена для каждого из каталогов видов. Я хочу объединить файлы с одинаковыми именами из 40 каталогов видов в один файл последовательностей, который имеет схожее имя.
Например, у меня есть следующие 3 каталога: "Species1", "Species2", "Species3". Внутри этих каталогов находятся файлы с похожими именами: "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 для переносимости, но это сделало бы скрипты немного короче.Вы хотите убедиться, что ваши шаблоны glob не слишком широкие, поэтому вы указываете
cat
использовать одно и то же имя файла для ввода и вывода. В противном случае вы можете очень быстро заполнить свой жесткий диск, поскольку попытаетесь создать файл бесконечного размера.Если вы указываете шаблон типа , и он не соответствует ни одному файлу, то используется
*.fasta
буквальная строка .*.fasta
Если у вас есть файл с именем
*.fasta
, то один из способов отличить его от шаблона — это проверить, читаем ли он.Прекращение
--
анализа аргументов — хорошая идея, если существуют подозрительные имена файлов.
Сначала простой сценарий.
# 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