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

相關內容