28

我在几个文件夹中有一些文件:

/home/d/folder1/a.txt
/home/d/folder1/b.txt
/home/d/folder1/c.mov
/home/d/folder2/a.txt
/home/d/folder2/d.mov
/home/d/folder2/folder3/f.txt

如何测量 /home/d/ 中所有 .txt 文件占用的磁盘空间总量?

我知道du 会给我一个给定文件夹的总空间,而ls -l 会给我单个文件的总空间,但是如果我想将所有 txt 文件相加并查看所有文件占用的空间怎么办 /home/d/ 中的所有 .txt 文件,包括文件夹 1 和文件夹 2 及其子文件夹(如文件夹 3),总共有一个巨大的 txt 文件?

4

13 回答 13

44

find folder1 folder2 -iname '*.txt' -print0 | du --files0-from - -c -s | tail -1

于 2009-08-31T19:10:56.690 回答
25

这将通过扩展报告以字节为单位的磁盘空间使用情况:

find . -type f -printf "%f %s\n" |
  awk '{
      PARTSCOUNT=split( $1, FILEPARTS, "." );
      EXTENSION=PARTSCOUNT == 1 ? "NULL" : FILEPARTS[PARTSCOUNT];
      FILETYPE_MAP[EXTENSION]+=$2
    }
   END {
     for( FILETYPE in FILETYPE_MAP ) {
       print FILETYPE_MAP[FILETYPE], FILETYPE;
      }
   }' | sort -n

输出:

3250 png
30334451 mov
57725092729 m4a
69460813270 3gp
79456825676 mp3
131208301755 mp4
于 2013-02-08T11:04:24.817 回答
16

简单的:

du -ch *.txt

如果您只想显示所占用的总空间,那么:

du -ch *.txt | tail -1
于 2013-10-04T17:39:23.673 回答
6

这是一种避免不良做法du的方法(在 Linux 中,使用 GNU coreutils和 Bash 语法):

total=0
while read -r line
do
    size=($line)
    (( total+=size ))
done < <( find . -iname "*.txt" -exec du -b {} + )
echo "$total"

如果要排除当前目录,请使用-mindepth 2with find

另一个不需要 Bash 语法的版本:

find . -iname "*.txt" -exec du -b {} + | awk '{total += $1} END {print total}'

请注意,这些不适用于包含换行符的文件名(但带有空格的文件名可以使用)。

于 2009-08-31T21:13:43.790 回答
5

苹果系统

  • 使用工具du和参数-I排除所有其他文件

Linux

-X, --exclude-from=FILE
              exclude files that match any pattern in FILE

--exclude=PATTERN
              exclude files that match PATTERN
于 2009-09-01T09:15:51.747 回答
4

这将做到:

total=0
for file in *.txt
do
    space=$(ls -l "$file" | awk '{print $5}')
    let total+=space
done
echo $total
于 2009-08-31T19:10:56.893 回答
3

GNU 发现,

find /home/d -type f -name "*.txt" -printf "%s\n" | awk '{s+=$0}END{print "total: "s" bytes"}'
于 2009-09-01T11:04:36.567 回答
2

建立在 ennukiller 的基础上,这将处理名称中的空格。我需要这样做并得到一个小报告:

查找 -type f -name "*.wav" | grep 导出 | ./calc_space

#!/bin/bash
# calc_space
echo SPACE USED IN MEGABYTES
echo
total=0
while read FILE
do
    du -m "$FILE"
    space=$(du -m "$FILE"| awk '{print $1}')
    let total+=space
done
echo $total
于 2010-08-22T16:50:49.107 回答
2

对于那些在 bash 上使用 GNU 工具的人来说,这是一个单一的衬里:

for i in $(find . -type f | perl -ne 'print $1 if m/\.([^.\/]+)$/' | sort -u); do echo "$i"": ""$(du -hac **/*."$i" | tail -n1 | awk '{print $1;}')"; done | sort -h -k 2 -r

您必须启用 extglob:

shopt -s extglob

如果你想让点文件工作,你必须运行

shopt -s dotglob

样本输出:

d: 3.0G
swp: 1.3G
mp4: 626M
txt: 263M
pdf: 238M
ogv: 115M
i: 76M
pkl: 65M
pptx: 56M
mat: 50M
png: 29M
eps: 25M

ETC

于 2015-08-28T12:20:22.310 回答
1

我的解决方案是获取给定路径和子目录中所有文本文件的总大小(使用 perl oneliner)

find /path -iname '*.txt' | perl -lane '$sum += -s $_; END {print $sum}'
于 2016-07-27T22:52:08.977 回答
0

我喜欢将 find 与 xargs 结合使用:

find . -name "*.txt" -print0 |xargs -0 du -ch

如果您只想查看总计,请添加尾部

find . -name "*.txt" -print0 |xargs -0 du -ch | tail -n1
于 2016-07-22T09:42:05.963 回答
0

对于任何想在命令行中使用 macOS 执行此操作的人,您需要基于 -print0 参数而不是 printf 的变体。上面的一些答案解决了这个问题,但这将通过扩展全面做到:

    find . -type f -print0 | xargs -0 stat -f "%N %i" |
  awk '{
      PARTSCOUNT=split( $1, FILEPARTS, "." );
      EXTENSION=PARTSCOUNT == 1 ? "NULL" : FILEPARTS[PARTSCOUNT];
      FILETYPE_MAP[EXTENSION]+=$2
    }
   END {
     for( FILETYPE in FILETYPE_MAP ) {
       print FILETYPE_MAP[FILETYPE], FILETYPE;
      }
   }' | sort -n
于 2018-12-27T20:05:09.007 回答
0

接受的答案有几个潜在的问题:

  1. 它不会进入子目录(不依赖非标准的 shell 功能,例如globstar
  2. 一般来说,正如下面丹尼斯威廉姆森所指出的,您应该避免解析ls
    • 即,如果用户或组(第 3 列和第 4 列)中有空格,则第 5 列将不是文件大小
  3. 如果你有一百万个这样的文件,这将产生百万个子shell,它会很慢

正如ghostdog74 所建议的,您可以使用 GNU 特定的-printf选项来find实现更强大的解决方案,避免所有过多的管道、子外壳、Perl 和奇怪的du选项:

# the '%s' format string means "the file's size"
find . -name "*.txt" -printf "%s\n" \
  | awk '{sum += $1} END{print sum " bytes"}'

是的,是的,使用pasteor的解决方案bc也是可能的,但不再那么简单了。

在 macOS 上,您需要使用 Homebrew 或 MacPorts 来安装findutils,然后调用gfind。(我在这个问题上看到了“linux”标签,但它也被标记为“unix”。)

如果没有 GNU find,您仍然可以回退到使用du

find . -name "*.txt" -exec du -k {} + \
  | awk '{kbytes+=$1} END{print kbytes " Kbytes"}'

…但是您必须注意,由于历史原因,du默认输出为512 字节块(请参阅手册页的“RATIONALE”部分),并且某些版本du(尤其是 macOS)甚至没有以字节为单位打印大小的选项。

这里有许多其他很好的解决方案(特别是参见Barn 的答案),但大多数都存在不必要的复杂性或过于依赖 GNU-only 功能的缺点——也许在您的环境中,没关系!

于 2019-09-12T19:05:44.830 回答