A maneira como você implementou o loop for
será interrompida se você tiver arquivos com espaços neles. Ele funcionará muito bem sem a variável for f in /path/to/files/*
, já que a expansão acontece de maneira que o loop for
possa entender.
Geralmente, como custa recursos para criar novos processos, é melhor ter apenas uma instância de awk
e, como observou @ jw013, você deve executar a divisão fora do shell, pois sh
e bash
são incapazes de matemática de ponto flutuante.
Como você precisa do conhecimento do final do arquivo para manipular cada linha, você tem duas opções: ler cada arquivo, salvar cada linha para a segunda leitura ou ler cada arquivo duas vezes. Como salvar arquivos grandes na memória pode ser problemático, optei pela segunda opção:
for f in /path/to/files/*; do
echo "$f"
awk '
NR == FNR {
sum += $4;
next;
}
FNR == 1 {
print "total: " sum;
SCALEFACTOR = 10000 / sum;
print SCALEFACTOR;
}
{
printf("%s\t%s\t%s\t%f\n", $1, $2, $3, $4 * SCALEFACTOR);
}' "$f" "$f"
NR == FNR
diz que o número do registro geral (linha) é o mesmo que o número do registro do arquivo atual, o que significa que você está no primeiro arquivo e a tarefa em questão é determinar a soma. next
impede que as outras cláusulas sejam disparadas. Caso contrário, se na primeira linha da segunda leitura do arquivo, fizermos o que você tinha entre suas chamadas awk
. Para cada linha na segunda leitura, imprimimos os quatro itens, com o quarto item dimensionado como você indicou.
Você pode usar a formatação de string padrão nesse quarto item, por exemplo, sua escala de cinco bc
comentada alteraria meu %f
para %.5f