Как сохранить информацию о файле в массиве?

Как сохранить информацию о файле в массиве?

С помощью этой части скрипта я могу получить необходимую информацию о файлах в моем каталоге (и подкаталогах). Единственная информация, которая мне нужна, это расширение и размер файла.

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

Это только часть скрипта. Так что мой вопрос: как мне поместить эту информацию в массив? Я имею в виду, что я хочу, чтобы массив с элементами выглядел так:

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

где c, h и txt — расширения файлов, а 123, 12 и 0 — размеры файлов. Так что в последнее время я могу работать с размерами и расширениями отдельно.
Надеюсь, я аккуратно изложил свой вопрос. Извините за ошибки. :)

решение1

Первый,не делайfor file in $(find …). Это очень хрупко.

Теперь вы можете немного упростить свой код, заставив find выводить имена файлов и их размеры вместе, используя -printf:

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

Затем вы можете использовать awkдля обработки этого вывода, чтобы получить кумулятивные размеры по расширению. Обратите внимание, что я использовал .для отделения имени файла ( %f) от размера ( %s), и добавил /после этого. Следовательно, я могу использовать .в качестве разделителя полей в awk. И поскольку единственными символами, не разрешенными в именах файлов, являются /и ASCII NUL, я могу безопасно использовать /в качестве разделителя записей.

Так:

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

Здесь я использую /в качестве индекса, если нет расширения.

В совокупности:

$ 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

Теперь, если ваши расширения не содержат пробелов, вы можете просто сделать:

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

Или вы можете использовать подстановку процесса и прочитать каждую запись в:

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

Как прежде:

$ printf "%s\n" "${my_arr[@]}"
h/780
md/2509
tex/23961
c/13557
//5109
txt/2349291
sh/1166
py/12248

решение2

Вот короткий bash-скрипт, который выполняет эту работу:

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

Связанный контент