Quero percorrer todos os arquivos do diretório.
os arquivos estão dispostos assim:
<Overall>4
other data
<Overall>2
other data
......
Eu tenho o código:
for file in .dat;
do
awk 'x+=sub(/<Overall>/,""){y+=$0} END{print FILENAME, y/x}' $file
done
isso imprime a média dos valores no arquivo, porém o que eu quero é pegar o diretório em que meu script está como argumento e executar o comando awk em todos os arquivos .dat do diretório.
Eu tentei usar o código:
for file in $1
mas receba o erro:
awk: cmd. line:1: fatal cannot open file `folder' for reading (No such file or directory)
Além disso, também quero poder classificar a saída dos valores médios de alto para baixo.
Responder1
Duas variações:
- Faça um loop nos arquivos e invoque
awk
uma vez para cada arquivo, ou - Forneça ao
awk
script todos os arquivos e deixe-o calcular a média de cada um e relatar à medida que avança.
A classificação do resultado de qualquer uma das soluções abaixo pode ser feita canalizando sua saída através
sort -k2,2rn
Isso faz uma classificação numérica reversa no segundo campo (as médias).
Primeira solução:
#!/bin/sh
for name in "$1"/*.dat; do
test -f "$name" || continue # skip non-files
awk -F '>' '/<Overall>/ { s+=$NF; n++ } END { print FILENAME, s/n }' "$name"
done
Este script espera um nome de diretório na linha de comando como o primeiro e único argumento da linha de comando. O awk
script encontrará todas as linhas que contêm a string Overall
e somará (in s
) o valor após o>
naquela linha. No final, a média é exibida junto com o nome do arquivo. A variável n
contém o número de vezes que adicionamos algo s
.
Segunda solução (requer GNU Awk):
#!/bin/sh
find "$1" -maxdepth 1 -type f -name '*.dat' \
-exec awk -F '>' '/<Overall>/ { s+=$NF; n++ } ENDFILE { print FILENAME, s/n; s=n=0 }' {} +
Este script, como o primeiro, espera um nome de diretório como seu único argumento de linha de comando. Ele usafind
para executar um awk
script com tantos .dat
arquivos quanto possível ao mesmo tempo.
O awk
script faz uso do GNU AwkENDFILE
para gerar os valores calculados e redefinir as variáveis s
e n
após o processamento de cada arquivo, antes de começar a ler o próximo arquivo.
Isso também pode ter sido escrito como
#!/bin/sh
awk -F '>' '/<Overall>/ { s+=$NF; n++ } ENDFILE { print FILENAME, s/n; s=n=0 }' "$1"/*.dat
mas isso depende de "$1"/*.dat
não expandir para uma lista muito longa de nomes de arquivos (isso também exige que cada .dat
nome seja um arquivo normal, o que é algo que o acimafind
comando acima garante -type f
).