for 循环中的 tee 未按预期工作

for 循环中的 tee 未按预期工作

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全部打印到标准输出(但是,我希望将完整输出用作 的输入java -jar varscan)。

这似乎最初可以工作,但该命令似乎没有完成(每个输出的文件大小比没有执行命令时要小tee)。

最终我得到一个错误,即这两个java -jar $varscan命令正在等待永远不会到达的输入(在有机会开始循环的第二次迭代之前)。

这是完成我所追求的目标的最佳方法,即在两个单独的命令中使用第一个命令的输出(理想情况下,根本不记录/打印第一个命令的输出)?tee与 for 循环不兼容?

提前致谢。

答案1

  1. 引用你的变量
  2. 不解析 ls
  3. 可选但推荐:简化您的脚本并不要重复自己。您使用 sed 生成基本名称两次,并每次为其附加不同的后缀 - 最好生成一次 - 这将减少错误的风险并提高可读性(并且略微提高性能 - 做某事“更便宜”一次并重新使用结果比执行完全相同的操作两次或更多次)。
  4. 可读性(即阅读和理解您编写的程序)是其中之一,如果不是的话编写代码时最重要的事情......因此,只要性能不是绝对重要的,最好优先以更易于理解的方式编写代码。这可能意味着插入更多的换行符或缩进,或者将长而复杂的命令分解为更短、更简单的命令。这将有助于现在编写和调试脚本,并且当您需要在 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 的 args 从 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

相关内容