在Shell中按扩展名计算文件总大小


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的各种组合,但是很难做到这一点。


您有在这个岗位这个问题的答案: serverfault.com/questions/183431/...
Blueicefield

您是否想知道每种文件的总大小或每种文件的总数?
user9517 2012年

请提供文件总大小。
barnybug,2012年

Answers:


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

它将输出找到的每种文件类型的大小(以字节为单位)。


谢谢,正在寻找可以进行任何扩展的摘要(例如
便于

检查我的更新。
user9517 2012年

太谢谢了。awk会为某些数字生成科学输出,可以将其禁用:.fdt 3.15152e + 10
barnybug 2012年

1
略微调整为仅给出普通整数:find。名称“ * $ {ft}” -print0 | xargs -0 du -c | grep总计| awk'{print $ 1}'
barnybug 2012年

1
可能要用来-iname使文件扩展名搜索不区分大小写。
亚伦·科普利2012年

6

使用bash版本4,你只需要调用findlsawk不是必要的:

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 sizeread size name-printf "%f\t%s\n"-printf "%s\t%f\n"应该修复它。
马特2015年

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


0

我使用以下两个命令解决了:

FILES=$(find . -name '*.c')
stat -c %s ${FILES[@]} | awk '{ sum += $1 } END { print ".c" " " sum }'

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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.