Estou tentando usar tee
em um loop for como tal:
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;
Ou seja, usando a saída de samtools mpileup
e canalizando isso em dois comandos separados. Eu adicionei o tail -n 5
para evitar que a saída de samtools mpileup
seja impressa em sua totalidade no stdout (no entanto, quero que a saída completa seja usada como entrada java -jar varscan
).
Isso parece funcionar inicialmente, mas o comando parece não ser concluído (o tamanho do arquivo para cada saída é menor do que se o comando fosse executado sem tee
).
Eventualmente, recebo um erro informando que os dois java -jar $varscan
comandos estão aguardando uma entrada que nunca chega (antes de ter a chance de iniciar a segunda iteração do loop).
Esta é a melhor maneira de realizar o que procuro, ou seja, usar a saída do primeiro comando em dois comandos separados (de preferência, sem gravar/imprimir a saída do primeiro comando)? É tee
incompatível com loops for?
Desde já, obrigado.
Responder1
- cite suas variáveis
- não analise ls
- opcional, mas recomendado: simplifique seu script enão se repita. Você gera o nome base duas vezes com sed e acrescenta um sufixo diferente a cada vez - seria melhor gerá-lo uma vez - isso reduziria o risco de bugs e melhoraria a legibilidade (e melhoraria um pouco o desempenho - é "mais barato" fazer algo uma vez e reutilizar o resultado do que fazer exatamente a mesma operação duas ou mais vezes).
- legibilidade (ou seja, a capacidade de ler eentenderum programa que você escreveu) é um dos, se nãooas coisas mais importantes ao escrever código....então, sempre que o desempenho não for absolutamente crítico, é melhor priorizar a escrita do seu código de uma forma que o torne mais fácil de entender. Isso pode significar inserir mais quebras de linha ou recuos, ou dividir comandos longos e complicados em comandos mais curtos e mais simples. Isso ajudará a escrever e depurar o script AGORA e também ajudará você a entendê-lo quando precisar revisitá-lo em X meses (ou anos).
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
Observe os vários níveis de recuo. por exemplo, tee é ligeiramente recuado de samtools, então os argumentos de tee são recuados de tee, e então a cauda volta ao mesmo nível de indentação de tee. Tudo isso ajuda a entender quais argumentos pertencem a qual programa e onde você está no pipeline (ou loop, etc.) enquanto o lê.
Aliás, barras invertidas para continuar uma linha são opcionais após uma barra vertical.
ou mesmo:
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