为什么 find -exec du 的总结不同?

为什么 find -exec du 的总结不同?

我在文件夹 /media/data/Selbstgemacht 中有家庭照片和电影,我想找到所有图片的大小。在 /media/data 中我使用find Selbstgemacht -type f -iname '*.jpg' -exec du -ch '{}' +它返回 5,1GB。
但是,如果我进入文件夹“Selbstgemacht”并使用find . -type f -iname '*.jpg' -exec du -ch '{}' +它,则会返回 7.0GB。

然后,我比较 find 的输出以检查它们是否找到相同的文件:
来自父文件夹find Selbstgemacht -type f -iname '*.jpg' -printf '%P\n' |sort > test1.txt
来自子文件夹 find . -type f -iname '*.jpg' -printf '%P\n' |sort > ../test2.txt

这些文件是相同的,因此两个 find 命令都找到完全相同的文件,这使我认为 du 报告大小的差异一定是由于其他原因造成的。

这里面到底是什么原因呢?

系统信息:

  • Debian 稳定版
  • 查找(GNU findutils)4.4.2
    • D_TYPE O_NOFOLLOW(启用)
    • LEAF_OPTIMISATION、FTS()、CBO(级别=0)
  • du(GNU coreutils)8.13

答案1

find ... -exec cmd {} +将根据需要执行cmd多次,以免打破传递给命令的参数大小的限制。

使用时find . -exec du {} +,文件列表的大小比使用时要小find verylongdirname -exec du {} +

因此,很可能find verylongdirname会运行du比该find .命令更多的命令。您最终看到的总数是上次运行的总数du,其中不包括所有文件(将会有更多文件)总计之前,您可以通过管道传输命令来grep 'total$'确认。

答案2

您应该看到的是,在这两种情况下您可能都无法获得图片的磁盘空间使用情况。如果您有数千张图片,则这两种情况都可能超出 exec 调用的限制。

为什么?该-exec (...) +命令将参数添加到execvp系统调用中。手册页定义了其底层系统调用的限制如下(摘自执行手册页):

Limits on size of arguments and environment
   Most UNIX implementations impose some limit on the total  size  of  the
   command-line argument (argv) and environment (envp) strings that may be
   passed to a new program. (...)

   On  kernel  2.6.23  and  later, most architectures support a size limit
   derived from the soft RLIMIT_STACK resource  limit  (see  getrlimit(2))
   that is in force at the time of the execve() call.  (...)   This change
   allows programs to have a much larger argument and/or environment list.
   For these  architectures,  the  total  size  is  limited  to 1/4 of the
   allowed stack size. (...) Since Linux 2.6.25, the kernel places a floor
   of 32 pages on this size limit, so that, even when RLIMIT_STACK is  set
   very low, applications are guaranteed to have at least as much argument
   and environment space as was provided by Linux 2.6.23 and earlier (This
   guarantee  was not provided in Linux 2.6.23 and 2.6.24.)  Additionally,
   the limit per string is 32 pages (the kernel constant  MAX_ARG_STRLEN),
   and the maximum number of strings is 0x7FFFFFFF.

因此,如果您的文件列表很长,您很快就会达到系统限制。此外,当相对路径较长时,它会使用更多内存,这会触发您更快地达到限制,因此两个命令的结果不同。

有一个解决方案

GNU 系统上的一个解决方案是使用文件输入列表来du使用--files0-from选项。以你的例子:

find Selbstgemacht -type f -iname '*.jpg' -print0 | du --files0-from=- -ch

第一个命令列出所有文件并将它们输出到标准输出上,以 NUL ( \0) 分隔。然后du从标准输入(文件名) “摄取”该列表-du总结总数。

相关内容