
Quiero recorrer todos los archivos del directorio.
los archivos están dispuestos así:
<Overall>4
other data
<Overall>2
other data
......
Tengo el codigo:
for file in .dat;
do
awk 'x+=sub(/<Overall>/,""){y+=$0} END{print FILENAME, y/x}' $file
done
esto imprime el promedio de los valores en el archivo, sin embargo, lo que quiero es tomar el directorio en el que se encuentra mi script como argumento y ejecutar el comando awk en todos los archivos .dat en el directorio.
Intenté usar el código:
for file in $1
pero aparece el error:
awk: cmd. line:1: fatal cannot open file `folder' for reading (No such file or directory)
Además de esto, también quiero poder ordenar la salida de valores promedio de mayor a menor.
Respuesta1
Dos variaciones:
- Recorra los archivos e invoque
awk
una vez para cada archivo, o - Proporcione al
awk
script todos los archivos y deje que calcule el promedio de cada uno e informe a medida que avanza.
La clasificación del resultado de cualquiera de las siguientes soluciones se puede realizar canalizando su salida a través de
sort -k2,2rn
Esto realiza una clasificación numérica inversa en el segundo campo (los promedios).
Primera solución:
#!/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 un nombre de directorio en la línea de comando como primer y único argumento de la línea de comando. El awk
script encontrará todas las líneas que contienen la cadena Overall
y resumirá (en s
) el valor después de >
esa línea. Al final, el promedio se genera junto con el nombre del archivo. La variable n
contiene el número de veces que le hemos agregado algo s
.
Segunda solución (requiere 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 el primero, espera un nombre de directorio como único argumento de línea de comando. Se utiliza find
para ejecutar un awk
script con tantos .dat
archivos como sea posible a la vez.
El awk
script utiliza el ENDFILE
disparador de GNU Awk para generar los valores calculados y restablecer las variables s
y n
después de procesar cada archivo, antes de comenzar a leer el siguiente archivo.
Esto también puede haber sido escrito como
#!/bin/sh
awk -F '>' '/<Overall>/ { s+=$NF; n++ } ENDFILE { print FILENAME, s/n; s=n=0 }' "$1"/*.dat
pero esto depende de "$1"/*.dat
no expandirse a una lista demasiado larga de nombres de archivos (esto también requiere que cada .dat
nombre sea un archivo normal, que es algo que el find
comando anterior garantiza con -type f
).