Recorra el directorio y sume el valor junto al patrón específico produciendo un promedio

Recorra el directorio y sume el valor junto al patrón específico produciendo un promedio

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:

  1. Recorra los archivos e invoque awkuna vez para cada archivo, o
  2. Proporcione al awkscript 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 awkscript encontrará todas las líneas que contienen la cadena Overally 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 ncontiene 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 findpara ejecutar un awkscript con tantos .datarchivos como sea posible a la vez.

El awkscript utiliza el ENDFILEdisparador de GNU Awk para generar los valores calculados y restablecer las variables sy ndespué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"/*.datno expandirse a una lista demasiado larga de nombres de archivos (esto también requiere que cada .datnombre sea un archivo normal, que es algo que el findcomando anterior garantiza con -type f).

información relacionada