![Как сохранить информацию о файле в массиве?](https://rvso.com/image/1087142/%D0%9A%D0%B0%D0%BA%20%D1%81%D0%BE%D1%85%D1%80%D0%B0%D0%BD%D0%B8%D1%82%D1%8C%20%D0%B8%D0%BD%D1%84%D0%BE%D1%80%D0%BC%D0%B0%D1%86%D0%B8%D1%8E%20%D0%BE%20%D1%84%D0%B0%D0%B9%D0%BB%D0%B5%20%D0%B2%20%D0%BC%D0%B0%D1%81%D1%81%D0%B8%D0%B2%D0%B5%3F.png)
С помощью этой части скрипта я могу получить необходимую информацию о файлах в моем каталоге (и подкаталогах). Единственная информация, которая мне нужна, это расширение и размер файла.
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