Расчет общего размера файла по расширению в оболочке

13

У нас есть набор каталогов, содержащих индексы Lucene. Каждый индекс представляет собой смесь различных типов файлов (различающихся по расширению), например:

0/index/_2z6.frq
0/index/_2z6.fnm
..
1/index/_1sq.frq
1/index/_1sq.fnm
..

(это около 10 разных расширений)

Мы хотели бы получить общее по расширению файла, например:

.frq     21234
.fnm     34757
..

Я пробовал различные комбинации du / awk / xargs, но мне было сложно сделать именно это.

barnybug
источник
У вас есть ответ на эту проблему в этом посте: serverfault.com/questions/183431/…
Blueicefield
Хотите узнать общий размер каждого типа файла или общее количество файлов каждого типа?
user9517
Общий размер файла, пожалуйста.
Барнибаг

Ответы:

19

Для любого данного расширения вы используете

find /path -name '*.frq' -exec ls -l {} \; | awk '{ Total += $5} END { print Total }'

чтобы получить общий размер файла для этого типа.

И после некоторого размышления

#!/bin/bash

ftypes=$(find . -type f | grep -E ".*\.[a-zA-Z0-9]*$" | sed -e 's/.*\(\.[a-zA-Z0-9]*\)$/\1/' | sort | uniq)

for ft in $ftypes
do
    echo -n "$ft "
    find . -name "*${ft}" -exec ls -l {} \; | awk '{total += $5} END {print total}'
done

Который будет выводить размер в байтах каждого найденного типа файла.

Iain
источник
Спасибо, искал что-то, что суммируется с любым расширением (как это было бы удобно, например, сортировать)
barnybug
Проверьте мое обновление.
user9517
большое спасибо. awk производит научный вывод для некоторых чисел, это можно отключить: .fdt 3.15152e + 10
barnybug
1
слегка подправлен, чтобы просто дать простые целые числа: найти. -name "* $ {ft}" -print0 | xargs -0 du -c | grep всего | awk '{print $ 1}'
barnybug
1
Возможно, вы захотите использовать это, -inameчтобы сделать поиск расширений файлов нечувствительным к регистру.
Аарон Копли
6

С bash version4 вам просто нужно позвонить find, lsа awkне обязательно:

declare -A ary

while IFS=$'\t' read name size; do 
  ext=${name##*.}
  ((ary[$ext] += size))
done < <(find . -type f  -printf "%f\t%s\n")

for key in "${!ary[@]}"; do 
  printf "%s\t%s\n" "$key" "${ary[$key]}"
done
Гленн Джекман
источник
Этот скрипт плохо работает с именами файлов с символом табуляции. Изменение read name sizeк read size nameи -printf "%f\t%s\n"к -printf "%s\t%f\n"должны это исправить.
Мэтт
1
Также обратите внимание, что этот скрипт плохо работает с файлами без расширения. Это будет рассматривать все имя файла как расширение. Добавьте if [ "$name" == "$ext" ]; then ext="*no_extension*"; fiпосле, ext=${name##*.}если вам нужно предотвратить это. Это поместит все файлы без расширения в *no_extension*группу (я использую, *no_extension*потому что *это не правильный символ в имени файла)
Мэтт
4

Каждый второй столбец разделен на .и последняя часть (расширение) сохранена в массиве.

#!/bin/bash

find . -type f -printf "%s\t%f\n" | awk '
{
 split($2, ext, ".")
 e = ext[length(ext)]
 size[e] += $1
}

END{
 for(i in size)
   print size[i], i
}' | sort -n

тогда вы получите общий размер каждого расширения в байтах.

60055 gemspec
321991 txt
2075312 html
2745143 rb
13387264 gem
47196526 jar
Сельман Улуг
источник
1

Расширение на сценарий Iain с более быстрой версией для работы с большим количеством файлов.

#!/bin/bash

ftypes=$(find . -type f | grep -E ".*\.[a-zA-Z0-9]*$" | sed -e 's/.*\(\.[a-zA-Z0-9]*\)$/\1/' | sort | uniq)

for ft in $ftypes
do
    echo -ne "$ft\t"
    find . -name "*${ft}" -exec du -bcsh '{}' + | tail -1 | sed 's/\stotal//'
done
MilesF
источник
0

Это решение:

find . -type f | grep -E ".*\.[a-zA-Z0-9]*$" | sed -e 's/.*\(\.[a-zA-Z0-9]*\)$/\1/' | sort | uniq -c | sort -n

Решение, изначально опубликованное в этом сообщении: получите все расширения и их количество файлов в каталоге

Blueicefield
источник
3
Это подсчет по количеству файлов, а не то, что я спрашивал - я бы хотел получить общее по размеру.
Барнибаг
0

Я решил использовать эти две команды:

FILES=$(find . -name '*.c')
stat -c %s ${FILES[@]} | awk '{ sum += $1 } END { print ".c" " " sum }'
c4f4t0r
источник
0

мой вариант ответа на вопрос:

#!/bin/bash

date >  get_size.log
# Lists all files
find . -type f -printf "%s\t%f\n" | grep -E ".*\.[a-zA-Z0-9]*$" | sort -h | awk  '
{
        split($2, ext, ".")
        e = ext[length(ext)]
        # Checks that one extension could be found
        if(length(e) < length($2)) {
                # Check that file size are bigger than 0
                if($i > 0) {
                        # Check that extension not are integer
                        if(!(e ~/^[0-9]+$/)) {
                                size[e] += $1
                        }
                }
        }
        if(length(e) == length($2)) {
                size["blandat"] += $1
        }
}

END{
 for(i in size)
   print size[i], i
}' | sort -n >> get_size.log
echo
echo
echo The result are in file get_size.log
Isterklister
источник
0

Попробуйте Crab ( http://etia.co.uk/ ) - это утилита командной строки, которая позволяет запрашивать файловую систему с помощью SQL.

Яцек Лампарт
источник