Как удалить четыре случайных символа перед расширением .extension из разных файлов с помощью цикла for?

Как удалить четыре случайных символа перед расширением .extension из разных файлов с помощью цикла for?

Я работаю над студенческим исследовательским проектом, который в значительной степени посвящен биоинформатике, и я иду по конвейеру обработки файлов. Немного предыстории: я работаю с метагеномными данными дробовика, которые представляют собой очень большие выборки A, T, G, C (нуклеотиды в образце ДНК), и, насколько я понял, некоторые квалификаторы. Я уже прошел несколько шагов конвейера, которые обрезали и очистили некоторые файлы, а также добавили некоторые квалификаторы. Важно то, что эти чтения в основном являются парными конечными чтениями, то есть два файла, считывающие нуклеотиды справа налево и слева направо.

До этого я забивал себе голову в основном только биологией и экологией, поэтому у меня нет никакого контекста для программирования или того, как/зачем что-то делать, или общих практик/функций и т. д. Вы поняли.

Тем не менее, я сам научился основам циклов for и манипуляции строками в UNIX, создав несколько файлов bash, которые проходили через разные папки, используя разные модули и функции. Вот пример кода:

cd ~/ncbi/public/sra/indian

for forward_read_file in *_1.fastq

do
rev=_2
reverse_read_file=${forward_read_file/_1/$rev}
perl /home/gomeza/shared/sharm646-2021-02-24-09_22/Softwares/NGSQCToolkit_v2.3.3/Trimming/AmbiguityFiltering.pl -i ${forward_read_file} -irev ${reverse_read_file} -c 1 -t5 -t3

rm ${forward_read_file} ${reverse_read_file}
done

#CAMEROON
cd ~/ncbi/public/sra/cameroon

for forward_read_file in *_1.fastq

do
rev=_2
reverse_read_file=${forward_read_file/_1/$rev}
perl /home/gomeza/shared/sharm646-2021-02-24-09_22/Softwares/NGSQCToolkit_v2.3.3/Trimming/AmbiguityFiltering.pl -i ${forward_read_file} -irev ${reverse_read_file} -c 1 -t5 -t3

rm ${forward_read_file} ${reverse_read_file}
done 

и так далее для многих папок. Я использовал манипуляцию строками, чтобы заставить каждую итерацию цикла for вызывать парные конечные файлы, а затем некоторые аргументы и параметры для используемого мной модуля.

Большая проблема, с которой я сейчас столкнулся, заключается в том, что я не могу придумать способ спарить конечные файлы для следующего шага в конвейере, поскольку они содержат четыре случайных символа прямо перед расширением, и я не могу их предсказать. Они не содержат значимых данных, поэтому мой план — удалить их из имен файлов и продолжить так, как я делал.

Вот примеры проблемных файлов; проблема в четырех символах в конце строки. Если я избавлюсь от них, я смогу выполнять манипуляции со строками как обычно.

SRR5898908_1_prinseq_good_ZsSX.fastq  SRR5898928_2_prinseq_good_VygO.fastq  SRR5898979_1_prinseq_good_CRzI.fastq  SRR6166642_2_prinseq_good_nqVP.fastq  SRR6166693_2_prinseq_good_y_OD.fastq
SRR5898908_2_prinseq_good_HPTU.fastq  SRR5898929_1_prinseq_good_p2mS.fastq  SRR5898979_2_prinseq_good_vYcE.fastq  SRR6166643_1_prinseq_good_fc8y.fastq  SRR6166694_1_prinseq_good_Ka1C.fastq
SRR5898909_1_prinseq_good_X41r.fastq  SRR5898929_2_prinseq_good_uO8g.fastq  SRR5898980_1_prinseq_good_WuPS.fastq  SRR6166643_2_prinseq_good_QUUK.fastq  SRR6166694_2_prinseq_good_ZlNk.fastq
SRR5898909_2_prinseq_good_GbmA.fastq  SRR5898930_1_prinseq_good_3qyA.fastq  

Где начало SRRxxxxx — это образец, а1или2являются прямым и обратным чтением соответственно, отсюда и мои манипуляции со строками. Проблема в четырех символах в конце строки. Если я избавлюсь от них, я смогу выполнять манипуляции со строками как обычно. Мой наставник рекомендовал мне как-то использовать функции FIND или CUT и говорил об использовании возврата find в качестве переменной для манипуляций, но я чувствую, что это все равно приведет к той же проблеме.

Как можно безопасно удалить эти символы с помощью цикла for? Или как вы считаете, это будет работать лучше всего.

Спасибо!

решение1

Попробуйте что-то вроде этого:

for forward_read_file in *_1*.fastq; do
   srr=$(echo "$forward_read_file" | cut -d_ -f1)
   rrf_array=( $(find . -name "${srr}_2_*.fastq") )

   case "${#rrf_array[@]}" in
     0) echo "Warning: No reverse read file found for $forward_read_file" > /dev/stderr ;;

     1) reverse_read_file="${rrf_array[1]}"
        perl /home/gomeza/shared/sharm646-2021-02-24-09_22/Softwares/NGSQCToolkit_v2.3.3/Trimming/AmbiguityFiltering.pl -i "$forward_read_file" -irev "$reverse_read_file" -c 1 -t5 -t3
        ;;

     *) echo "Error: multiple reverse read files found for $forward_read_file" > /dev/stderr ;;
   esac

done

Это перебирает все _1файлы. Он использует cutдля извлечения идентификатора образца SRR, а затем использует его с findкомандой для поиска любых соответствующих _2файлов. findВывод сохраняется в массиве, поскольку мы не знаем, сколько результатов может быть возвращено.

Он обрабатывает три возможных результата: ни одного совпадения (плохо), ровно 1 совпадение (хорошо, это то, что нам нужно) и более 1 совпадения (опять же, плохо).

Если результат только один, извлеките соответствующий файл из массива и обработайте его с помощью вашего скрипта Perl.

Если есть ноль или более одного результата, вывести предупреждающее сообщение в stderr и продолжить к следующему _1имени файла. Вы можете добавить ; exit 1(или другой код для обработки ошибки) перед ;;для этих случаев, если хотите.

При этом игнорируются все части имен файлов, за исключением идентификатора образца SRR в начале и символа _1или _2, который идентифицирует его как файл прямого или обратного сопряжения.

Кстати, это можно было бы сделать с помощью оператора if; then; elseвместо оператора case, но я подумал, что было бы полезно обрабатывать случаи «ноль» и «более одного». Например:

if [ "${#rrf_array[@]}" == 1 ]; 
  reverse_read_file="${rrf_array[1]}"
  perl /home/gomeza/shared/sharm646-2021-02-24-09_22/Softwares/NGSQCToolkit_v2.3.3/Trimming/AmbiguityFiltering.pl -i "$forward_read_file" -irev "$reverse_read_file" -c 1 -t5 -t3
else
  echo "Warning: unknown problem with reverse read file for $forward_read_file" > /dev/stderr
fi

Если вы просто хотите игнорировать «проблемные» файлы, удалите блок else.


Кстати, чтобы сделать ваш сценарий более читабельным, я предлагаю сделать что-то вроде этого в верхней части сценария:

AFilter='/home/gomeza/shared/sharm646-2021-02-24-09_22/Softwares/NGSQCToolkit_v2.3.3/Trimming/AmbiguityFiltering.pl'

и позже:

perl "$AFilter" -i "$forward_read_file" -irev "$reverse_read_file" -c 1 -t5 -t3

В качестве альтернативы, если скрипт(ы) perl являются исполняемыми (т. е. имеют #!/usr/bin/perlили аналогичную строку shebang и установлен флаг исполняемости с помощью chmod +x), вы можете просто добавить /home/gomeza/shared/sharm646-2021-02-24-09_22/Softwares/NGSQCToolkit_v2.3.3/Trimming/в свой $PATH:

PATH="$PATH:/home/gomeza/shared/sharm646-2021-02-24-09_22/Softwares/NGSQCToolkit_v2.3.3/Trimming"

и запустите скрипт как:

AmbiguityFiltering.pl -i "$forward_read_file" -irev "$reverse_read_file" -c 1 -t5 -t3

решение2

Вы имеете в виду переименование названия?

Так:

cat a2 | sed -e 's|\(.*\)\(good_\)\(.*\)\(.fastq\)|mv \1\2\3\4 \1\2\4|'
mv SRR5898908_1_prinseq_good_ZsSX.fastq SRR5898908_1_prinseq_good_.fastq
mv SRR5898928_2_prinseq_good_VygO.fastq SRR5898928_2_prinseq_good_.fastq

Связанный контент