Con esta parte del script puedo obtener la información necesaria sobre los archivos en mi directorio (y subdirectorios). La única información que necesito es la extensión y el tamaño del archivo.
for file in `find . -type f`; do
size=$(stat -c '%s' ${file})
file=$(echo "${file}" | awk -F/ '{print $NF}')
ext=$(echo "${file}" | grep '..*\.' | awk -F. '{print $NF}' | grep '[A-Za-z0-9]')
if [ -z ${ext} ]; then
echo "NOTE: no extention"
else
EXTS="${EXTS}${ext}${newLine}"
Es sólo una parte del guión. Entonces mi pregunta es: ¿Cómo puedo poner esta información en una matriz? Quiero decir que quiero una matriz con elementos que se vea así:
c/123 /12 h/90 /0 txt/0
donde c, h y txt son extensiones de archivo y 123, 12 y 0 son tamaños de archivo. Últimamente puedo trabajar por separado con tamaños y extensiones.
Espero haber dejado mi pregunta claramente. Lo siento por los errores. :)
Respuesta1
Primero,no lo hagasfor file in $(find …)
. Eso es muy frágil.
Ahora, puedes simplificar un poco tu código haciendo que find imprima los nombres de archivos y los tamaños juntos, usando -printf
:
find . -type f -printf '%s.%f/'
Luego, puede utilizar awk
para procesar esta salida para obtener tamaños acumulativos por extensión. Tenga en cuenta que solía .
separar el nombre del archivo ( %f
) del tamaño ( %s
), y agregué un /
después de eso. Por lo tanto, puedo usarlo .
como separador de campos en awk
. Y dado que los únicos caracteres no permitidos en los nombres de archivos son /
ASCII NUL, puedo usarlos de forma segura /
como separador de registros.
Entonces:
awk -F. -v RS=/ 'NF > 2 {size[$NF] += $1; next}
{size["/"] += $1}
END {for (i in size) {print i,"/",size[i]}'
Aquí, lo estoy usando /
como índice si no hay extensión.
Conjunto:
$ find . -type f -printf '%s.%f/' | awk -F. -v RS=/ 'NF > 2 {size[$NF] += $1; next}
{size["/"] += $1}
END {for (i in size) {printf "%s/%d\n", i, size[i]}}'
h/780
md/2509
tex/23961
c/13557
//5109
txt/2349291
sh/1166
py/12248
Ahora, si tus extensiones no contienen espacios, puedes simplemente hacer:
my_array=( $(find . -type f -printf '%s.%f/' | awk -F. -v RS=/ 'NF > 2 {size[$NF] += $1; next} {size["/"] += $1} END {for (i in size) {printf "%s/%d\n", i, size[i]}}') )
O puede utilizar la sustitución de procesos y leer cada entrada en:
my_arr=()
while IFS='' read -r entry
do
my_arr+=( "$entry" )
done < <(find . -type f -printf '%s.%f/' | awk -F. -v RS=/ 'NF > 2 {size[$NF] += $1; next} {size["/"] += $1} END {for (i in size) {printf "%s/%d\n", i, size[i]}}')
Como antes:
$ printf "%s\n" "${my_arr[@]}"
h/780
md/2509
tex/23961
c/13557
//5109
txt/2349291
sh/1166
py/12248
Respuesta2
Aquí hay un breve script de bash que está haciendo el trabajo:
i=0
while read -r -d $'\0' file
do
size=$(stat -c '%s' ${file})
ext=`basename $file | sed -re "s/^[^.]+.*\.//"`
if [ -z "$ext" ] || [ "$ext" = "`basename $file`" ] ; then
echo "NOTE: no extention ($file)"
else
extensions[$i]="$ext"
sizes[$((i++))]=$size
fi
done < <(find . -type f -print0)
for (( j=0 ; j<i; j++ )) do
echo index: $j / extension: ${extensions[$j]} / size: ${sizes[$j]}
done