Linux中名称与正则表达式匹配的文件的磁盘使用情况?

时间:2012-02-28 16:41:15

标签: regex linux bash sum diskspace

所以,在很多情况下我想知道我的磁盘空间占用了多少,所以我知道要摆脱什么,转换成另一种格式,存储在别处(如数据DVD),转移到另一个分区等。在这种情况下,我正在查看SliTaz Linux可启动媒体的Windows分区。

在大多数情况下,我想要的是文件和文件夹的大小,为此我使用基于NCurses的ncdu

ncdu

但在这种情况下,我想要一种方法来获得 所有匹配正则表达式 的文件的大小。 .bak文件的示例正则表达式:

.*\.bak$

如何考虑使用核心GNU实用程序或BusyBox的标准Linux,我如何获取该信息?

编辑:输出旨在由脚本解析。

6 个答案:

答案 0 :(得分:43)

我建议像:find . -regex '.*\.bak' -print0 | du --files0-from=- -ch | tail -1

一些注意事项:

  • -print0的{​​{1}}选项和find的{​​{1}}可以避免文件名中的空白问题
  • 正则表达式与整个路径匹配,例如--files0-from,而不仅仅是du,所以如果你修改它,请考虑到这一点
  • 我使用du ./dir1/subdir2/file.bak标志来生成“人类可读”的格式,但是如果要解析输出,最好使用file.bak(总是使用千字节)
  • 如果删除h命令,您还将看到特定文件和目录的大小

Sidenote:一个很好的GUI工具,可以找出谁占用你的磁盘空间FileLight。它没有正则表达式,但是非常方便查找阻塞磁盘的大目录或文件。

答案 1 :(得分:22)

du是我最喜欢的答案。如果您有固定的文件系统结构,则可以使用:

du -hc *.bak

如果您需要添加子目录,只需添加:

du -hc *.bak **/*.bak **/**/*.bak

等等

但是,这不是一个非常有用的命令,所以使用你的find:

TOTAL=0;for I in $(find . -name \*.bak); do  TOTAL=$((TOTAL+$(du $I | awk '{print $1}'))); done; echo $TOTAL

这将回显您找到的所有文件的总大小(以字节为单位)。

希望有所帮助。

答案 2 :(得分:3)

在Bourne Shell中运行此命令以声明一个函数,该函数计算当前目录中与正则表达式模式匹配的所有文件的大小总和:

sizeofregex() { IFS=$'\n'; for x in $(find . -regex "$1" 2> /dev/null); do du -sk "$x" | cut -f1; done | awk '{s+=$1} END {print s}' | sed 's/^$/0/'; unset IFS; }

(或者,您可以将其放在脚本中。)

<强>用法:

cd /where/to/look
sizeofregex 'myregex'

结果将是一个数字(以KiB为单位),包括0(如果没有与您的正则表达式匹配的文件)。

如果您不希望它在其他文件系统中查找(假设您要查找.so下的所有/个文件,这是/dev/sda1的挂载,但不在/home下{1}},/dev/sdb1的附加内容,在上面的函数中向-xdev添加find参数。

答案 3 :(得分:3)

之前的解决方案对我来说无法正常工作(我遇到了管道问题du),但以下方法效果很好:

find path/to/directory -iregex ".*\.bak$" -exec du -csh '{}' + | tail -1

iregex选项是不区分大小写的正则表达式。如果您希望区分大小写,请使用regex

如果您对正则表达式不满意,可以使用inamename标志(前者不区分大小写):

find path/to/directory -iname "*.bak" -exec du -csh '{}' + | tail -1

如果您想要每个匹配的大小(而不仅仅是合计的总数),只需省略管道尾命令:

find path/to/directory -iname "*.bak" -exec du -csh '{}' +

这些方法避免了@MaddHackers回答中的子目录问题。

希望这可以帮助处于相同情况的其他人(在我的情况下,查找.NET解决方案中所有DLL的大小)。

答案 4 :(得分:1)

如果你对glob-patterns没问题,而你只对当前目录感兴趣:

stat -c "%s" *.bak | awk '{sum += $1} END {print sum}'

sum=0
while read size; do (( sum += size )); done < <(stat -c "%s" *.bak)
echo $sum

stat的%s指令给出字节而不是千字节。

如果您希望使用bash版本4进入子目录,可以shopt -s globstar并使用模式**/*.bak

答案 5 :(得分:1)

接受的回复建议使用

find . -regex '.*\.bak' -print0 | du --files0-from=- -ch | tail -1

但由于du在我的系统上不知道--files-0-from选项,因此无法在我的系统上运行。只有GNU du知道该选项,它既不是POSIX Standard的一部分(所以你不能在FreeBSD或macOS中找到它),你也不会在{{3}找到它(例如,大多数嵌入式Linux系统)或任何其他不使用GNU du版本的Linux系统。

然后有回复建议使用:

find path/to/directory -iregex .*\.bak$ -exec du -csh '{}' + | tail -1

只要找不到太多文件,此解决方案就可以正常运行,因为+表示find会尝试使用尽可能多的点击来调用du但是,单个调用可能存在系统支持的最大参数数量(N),如果命中数超过此值,find将多次调用du,将命中数分成较小的组大于或等于每个N项,这种情况下结果将是错误的,只显示最后du次呼叫的大小。

最后有一个使用statawk的答案,这是一个很好的方法,但它依赖于shell globbing,只有Bash 4.x或更高版本支持。它不适用于旧版本,如果它与其他shell一起使用是不可预测的。

POSIX一致性解决方案(适用于Linux,macOS和任何BSD变体),不会受到任何限制,并且肯定适用于每个shell:

find . -regex '.*\.bak' -exec stat -f "%z" {} \; | awk '{s += $1} END {print s}'