Como armazenar informações de arquivo em um array?

Como armazenar informações de arquivo em um array?

Com esta parte do script posso obter as informações necessárias sobre os arquivos em meu diretório (e subdiretórios). A única informação que preciso é a extensão e o tamanho do arquivo.

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}"

É apenas parte do roteiro. Então minha dúvida é: Como posso colocar essas informações em um array? Quero dizer, quero que um array com elementos fique assim:

 c/123 /12 h/90 /0 txt/0

onde c, h e txt são extensões de arquivo e 123, 12 e 0 são tamanhos de arquivo. Ultimamente, posso trabalhar separadamente com tamanhos e extensões.
Espero ter formulado minha pergunta de maneira organizada. Desculpe pelos erros. :)

Responder1

Primeiro,não façafor file in $(find …). Isso é muito frágil.

Agora, você pode simplificar um pouco seu código fazendo com que find imprima os nomes e tamanhos dos arquivos juntos, usando -printf:

find . -type f -printf '%s.%f/'

Em seguida, você pode usar awkpara processar essa saída para obter tamanhos cumulativos por extensão. Observe que eu costumava .separar o nome do arquivo ( %f) do tamanho ( %s) e adicionei um /depois disso. Portanto, posso usar .como separador de campos em awk. E como os únicos caracteres não permitidos em nomes de arquivos são /ASCII NUL, posso usá-los com segurança /como separador de registros.

Então:

awk -F. -v RS=/ 'NF > 2 {size[$NF] += $1; next}
  {size["/"] += $1}
END {for (i in size) {print i,"/",size[i]}'

Aqui, estou usando /como índice se não houver extensão.

Combinado:

$ 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

Agora, se suas extensões não contiverem espaços, você poderia simplesmente fazer:

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]}}') )

Ou você pode usar a substituição de processo e ler cada entrada em:

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

Responder2

Aqui está um pequeno script bash que está fazendo o trabalho:

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

informação relacionada