Цикл Bash для двух наборов файлов одновременно

У меня есть два набора файлов в одном каталоге:

1.bam 
2.bam
3.bam

и

1.txt
2.txt
3.txt

Мне нужно запустить команду, в которой 1.bam и 1.txt интерпретируются вместе и так далее..

Я попробовал перебрать индексы массива:

bam=(*.bam)
ids=(*.txt)

for i in ${#bam[@]}; do     
 f=${bam[i]}    
 e=${ids[i]}
 samtools view -N $e $f 
done

И параллельно:

parallel --dry-run 'samtools view -N {1} {2} > {2.}.fasta' ::: *txt ::: *bam

С --dry-run я вижу, что цикл повторяется 3 раза (3 набора файлов * 3 цикла); Мне нужен только один.

Любая помощь?

Перебрать индексы, например: for i in "${!bam[@]}"

Jetchisel 17.07.2024 15:36

Просто.. Спасибо.

pedro 17.07.2024 15:37

А как насчет параллельной команды? Вы видите что-то не так?

pedro 17.07.2024 15:37

Просто передайте файлы .bam в GNU Parallel и получите соответствующий текстовый файл так же, как вы получаете выходной файл parallel 'samtools view -N {1.}.txt {1} > {1.}.fasta' ::: *.bam

Mark Setchell 17.07.2024 15:50

Если некоторые файлы отсутствуют, наборы будут смещены.

Kaz 18.07.2024 06:34

Конечно, но насчет количества парных файлов я уверен.

pedro 18.07.2024 09:26

Я голосую за закрытие этого вопроса, потому что на плакате не использовался shellcheck.net , как указано в теге bash.

Ed Morton 18.07.2024 13:11
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
9
70
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Во-первых, ${#bam[@]} сообщает количество элементов в bam.
. Как упоминал Джетчизель в комментариях, вам нужен "${!bam[@]}", который возвращает индексы.

$: touch {1..3}.{bam,txt}
$: ls
1.bam  1.txt  2.bam  2.txt  3.bam  3.txt

$: bam=(*.bam); ids=(*.txt)
$: echo "${bam[@]} ${ids[@]}"
1.bam 2.bam 3.bam 1.txt 2.txt 3.txt

$: for i in ${#bam[@]}; do f=${bam[i]}; e=${ids[i]}; echo "i='$i' f='$f' e='$e'"; done
i='3' f='' e=''

$: echo "#:'${#bam[@]}' !:'${!bam[@]}'"
#:'3' !:'0 1 2'

$: for i in ${!bam[@]}; do f=${bam[i]}; e=${ids[i]}; echo "i='$i' f='$f' e='$e'"; done
i='0' f='1.bam' e='1.txt'
i='1' f='2.bam' e='2.txt'
i='2' f='3.bam' e='3.txt'

Это предполагает, что массивы будут действительно параллельными. Я оставляю вам проверку ошибок, если вы не попросите более глубокого погружения в это.

Есть и другие способы подойти к этому. Если вы предполагаете использовать настоящие параллельные массивы, вы также можете вернуться к ним, выполнив итерацию одного и взламывая строки другого.

$: for b in ${bam[@]}; do echo "b='$b' t='${b%.bam}.txt'"; done
b='1.bam' t='1.txt'
b='2.bam' t='2.txt'
b='3.bam' t='3.txt'

Но вы можете явно интерполировать имена файлов с помощью расширения фигурных скобок -

$: for i in ${!bam[@]}; do echo "samtools view -N" $i.{bam,txt}; done
samtools view -N 0.bam 0.txt
samtools view -N 1.bam 1.txt
samtools view -N 2.bam 2.txt

Поэтому я бы сделал это примерно так:

for i in ${!bam[@]}
do samtools view -N $i.{bam,txt} > $i.fasta 2> $i.log & 
done

По привычке я обычно цитирую эти переменные, но в данном случае это все целочисленные индексы, и цитирование {bam,txt} нарушает их, поэтому вам придется исключить их из ненужных в противном случае (по обстоятельствам) кавычек, поэтому я просто оставил их. выключен по этому поводу.

"$i".{bam,txt} цитирует ту часть, которую нужно процитировать.
tripleee 17.07.2024 16:19

Да, но это всего лишь цифра, лол

Paul Hodges 17.07.2024 16:28

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

tripleee 17.07.2024 16:29

100% согласен. Спасибо.

Paul Hodges 17.07.2024 16:29

Что ж, спасибо за помощь.

pedro 17.07.2024 17:51

Вот конвейерный способ сделать это:

printf "%s\n" *.{bam,txt} \
| sort \
| while IFS= read -r bamfile; IFS= read -r txtfile; do
    echo "do something with '${bamfile}' and '${txtfile}'"
  done
do something with '1.bam' and '1.txt'
do something with '2.bam' and '2.txt'
do something with '3.bam' and '3.txt'

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

printf "%s\0" *.{bam,txt} \
| sort -z \
| while IFS= read -d '' -r bamfile; IFS= read -d '' -r txtfile; do
    echo "do something with '${bamfile}' and '${txtfile}'"
  done

Интересно, спасибо за это.

pedro 18.07.2024 09:28

Другие вопросы по теме