тройник в цикле не работает как ожидалось

тройник в цикле не работает как ожидалось

Я пытаюсь использовать teeв цикле for следующее:

for ea in $(ls *bam)
  do samtools mpileup -f $ref $ea | \
  tee \
  >(java -jar $varscan2 mpileup2indel --output-vcf 1 > vcf/"$(echo $ea | sed s/.bam//)"_mpileup2indel.vcf) \
  >(java -jar $varscan2 mpileup2snp --output-vcf 1 > vcf/"$(echo $ea | sed s/.bam//)"_mpileup2snp.vcf) | \
  tail -n 5
done;

То есть, используя вывод samtools mpileup, и передавая его в две отдельные команды. Я добавил , tail -n 5чтобы предотвратить вывод вывода samtools mpileupполностью на stdout ( java -jar varscanоднако я хочу, чтобы полный вывод использовался в качестве ввода для ).

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

В конце концов я получаю сообщение об ошибке, сообщающее о том, что обе java -jar $varscanкоманды ожидают ввода, который так и не поступает (до того, как появляется возможность начать вторую итерацию цикла).

Является ли это лучшим способом добиться того, что мне нужно, т. е. использовать вывод первой команды в двух отдельных командах (в идеале вообще не записывать/не выводить вывод первой команды)? Несовместимо teeс циклами for?

Заранее спасибо.

решение1

  1. указывайте свои переменные
  2. не анализировать ls
  3. необязательно, но рекомендуется: упростите свой сценарий ине повторяйся. Вы генерируете базовое имя дважды с помощью sed и каждый раз добавляете к нему другой суффикс — лучше сгенерировать его один раз — это снизит риск ошибок и улучшит читаемость (и совсем немного улучшит производительность — «дешевле» сделать что-то один раз и повторно использовать результат, чем выполнять одну и ту же операцию дважды или более).
  4. читабельность (т.е. способность читать ипониматьпрограмма, которую вы написали) является одним из, если неtheсамые важные вещи при написании кода... поэтому, всякий раз, когда производительность не является абсолютно критической, лучше отдать приоритет написанию кода таким образом, чтобы его было легче понять. Это может означать вставку большего количества переносов строк или отступов, или разбиение длинных и сложных команд на более короткие и простые команды. Это поможет написать и отладить скрипт СЕЙЧАС, а также поможет вам понять его, когда вам нужно будет вернуться к нему через X месяцев (или лет).
for ea in *.bam; do
  bn="$(basename "$ea" .bam)"
  samtools mpileup -f "$ref" "$ea" |
    tee \
      >(java -jar "$varscan2" mpileup2indel --output-vcf 1 > "vcf/${bn}_mpileup2indel.vcf") \
      >(java -jar "$varscan2" mpileup2snp --output-vcf 1 > "vcf/${bn}_mpileup2snp.vcf") |
    tail -n 5
done

Обратите внимание на различные уровни отступов. Например, tee немного отступает от samtools, затем аргументы tee отступают от tee, а затем хвост возвращается на тот же уровень отступа, что и tee. Все это помогает понять, какие аргументы принадлежат какой программе, и где в конвейере (или цикле и т. д.) вы находитесь, когда читаете его.

Кстати, обратная косая черта для продолжения строки после символа вертикальной черты необязательна.

или даже:

outdir="vcf"

for ea in *.bam; do
  bn="$(basename "$ea" .bam)"
  indel="$outdir/${bn}_mpileup2indel.vcf"
  snp="$outdir/${bn}_mpileup2snp.vcf"

  samtools mpileup -f "$ref" "$ea" |
    tee \
      >(java -jar "$varscan2" mpileup2indel --output-vcf 1 > "$indel") \
      >(java -jar "$varscan2" ​mpileup2snp --output-vcf 1 > "$snp") |
 ​   tail -n 5
done

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