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
- 引用你的變數
- 不解析 ls
- 可選但建議:簡化您的腳本並不要重複自己。您使用 sed 生成基本名稱兩次,並每次為其附加不同的後綴 - 最好生成一次 - 這將減少錯誤的風險並提高可讀性(並且會略微提高性能 - 做某事“更便宜”一次並重新使用結果比執行完全相同的操作兩次或更多次)。
- 可讀性(即閱讀和理解您編寫的程式)是其中之一,如果不是的話這編寫程式碼時最重要的事情......因此,只要效能不是絕對重要的,最好優先以更易於理解的方式編寫程式碼。這可能意味著插入更多的換行符或縮進,或將長而複雜的命令分解為更短、更簡單的命令。這將有助於現在編寫和調試腳本,並且當您需要在 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