如何从根目录计算系统上的所有文件?


4

我想知道服务器上的文件总数。能做到吗?


2
对于不扫描整个文件系统的粗略估计(也计算目录),这里有df -i
西蒙·里希特

Answers:


6

根据要精确计数的数量,最好对每个文件系统执行此操作而不要对根目录下的所有文件进行计数。计算根目录下的所有内容还将计算您可能不希望包含的文件/proc/sys文件。

要使用GNU计算根文件系统上的所有内容find,您可以执行以下操作:

find / -xdev -type f -printf '\n' | wc -l

-printf '\n'将只打印一个换行符对找到的每个文件,而不是文件名。这样,文件名本身就包含换行符并可以算作多个文件,就不会有问题。

使用POSIX查找,您可以轻松地做到:

find / -xdev -type f | wc -l

或POSIXly,并避免对包含换行符的任何文件进行两次计数:

{ printf 0; find / -xdev -type f -exec sh -c 'printf "+ $#"' sh {} +; echo; } | bc

在这里,每个文件成为一个不同的自变量sh,然后向其输出自变量的总数。如果sh调用了多个进程(就像许多文件一样),则将每个sh输出相加bc

更新资料

一个较简单(但较慢)的POSIX解决方案:

find / -xdev -type f -exec printf '%s\0' {} + | tr '\n\0' '?\n' | wc -l

更新2

正如@Gilles所指出的那样-type fwith find仅用于计数常规文件。要包含设备文件,可以使用-type f -o -type b -o -type c。要同时计算目录,请不要使用任何-type选项。

Gilles的另一点是,具有多个硬链接的文件将被计为不同的文件。这在文件系统上可能是不希望的,例如,通过将较新的树中的未更改文件硬链接至较旧的树中的文件,已创建了增量备份树。要使用GNU工具克服此问题,您可以执行以下操作:

find / -xdev -type f -printf '%i\n' | sort -u | wc -l

使用POSIX工具:

find / -xdev -type f -exec ls -iq {} + | sort -buk 1,1 | wc -l

文件名中的换行符没有问题,因为-q选项ls表示它将用替换?


回显的-n选项不是POSIX。使用外壳的printf
jordanm 2014年

@jordanm,谢谢,固定。也错过了的哑元$0参数sh,如果没有它,则每次sh运行的计数将为一。
Graeme 2014年

为什么-type f呢 该问题要求提供文件计数,而不是常规文件计数。请注意,如果所有这些方法都有多个硬链接(不包括目录链接...指向目录的链接),则它们对文件进行多次计数。
Gilles 2014年

@吉尔斯,好点,更新。
Graeme

@Graeme,而不是sort -buk 1,1,我们可以只用做同样的事情sort -buk 1吗?man sortKEYDEF is F[.C][OPTS][,F[.C][OPTS]]。因为我们按索引节点号排序,所以仅字段1似乎足够。
MS.Kim 2014年

2

df -i /为您提供根文件系统(使用inode的文件系统上,包括ext2 / ext3 / ext4系列但不包括btrfs)上已使用的inode的数量。这是该文件系统上文件的数量,以及为使用fsck而预先分配的一些inode 。

如果想要目录树中的文件数,则可以使用以下命令:

du -a /some/directory | wc -l

添加选项-xdu,如果你不想安装遍历点,例如du -ax / | wc -l。请注意,如果文件名包含换行符,则返回的计数将更大(一个不错的主意,但并非没有可能)。

另一种计算方法是

find /some/directory | wc -l

或者,为了处理包含换行符的文件名,可以使用GNU find(非嵌入式Linux或Cygwin):

find /some/directory -printf . | wc -c

添加-xdev(例如find /some/directory -xdev -printf .)以跳过安装点。请注意,此目录条目是文件,而不是文件:如果文件具有多个硬链接,则将对每个链接进行计数(而dfdu方法对文件进行计数,即,到同一文件的多个硬链接仅被计数一次)。


这是非常好的一点。我不知道为什么我没有做到这一点,只是我必须变得老迈,因为几天前我也提出了同样的观点。并感谢您指出-f事情-那也是我也犯的一个严重错误。您可以使用/./很少使用所有文件名,换行符或否。unix.stackexchange.com/a/122871/52934
mikeserv

2

更新

我可以想象这是最快的方法,可以完全移植。我tar在下面使用,因为它只会自动添加一次硬链接文件:

   find /./ -xdev ! -type d | tar -cf - - | tar -t | sed -n '\|^/\./|c.' | wc -l

便携式且非常快速:

find / -xdev | sed -n '/^[./]/c\.' | wc -l

我不相信您确实需要所有其他内容-尽管@Graeme对于以下可能的遗漏是正确的。但是,这没有相同的缺点:

find /./ -xdev | sed -n '\|^/\./|c.' | wc -l

您需要做的就是确保完整的root路径,而不必跳过所有其他问题。

注意:正如Gilles指出的那样,使用-type f是一个巨大的错误。我更新了这篇文章以反映这一点。

同样,为了获得更准确的计数,您只需执行以下操作:

du / --inodes -xs

只要您的工具是最新的,它将为您提供根文件系统中确切数量的文件。这也可以用于任何目录。

这是仅使用非常常用的工具即可获得任何文件系统或子目录中所有文件(不包括硬链接)的准确计数的一种方法。首先以mount --bind远距离隔离目标根:

mkdir /tmp/ls ; sudo mount -B / $_ ; cd $_

接下来,计算您的文件:

sudo ls -ARUi1 ./ | 
grep -o '^ *[0-9]*' | 
sort -un | 
wc -l

几天前,我对另一个答案做了非常类似的事情-尽管那有点复杂,因为目标是按包含最大文件数的子目录进行排序-所以那里的命令看起来和这里的命令有些不同。顺便说一下,但这仍然非常快。

无论如何,其核心是ls命令。它-Recursively搜索整个树,列出-Almost-all -inodes -Unsorted-1每行文件。然后,我们grep -only的索引节点[0-9]numbers, sort-unique -numberswcount -lines.


1
尽管确实会减少名称失败的范围,但仍然无法为笨拙的命名文件提供任何保证。find无论如何,计数文件的开销应始终比其本身少。
Graeme 2014年

@Graeme它将完全删除文件名。在什么情况下会错过?就开销而言,您的答案似乎是每个文件调用一个shell?我需要仔细观察...
mikeserv

在点之前包含换行符的文件名将被计算两次。目录下的名称以换行符结尾的文件也将被计数两次。排除具有多个文件名的所有边缘情况的唯一可靠方法是以某种方式将每个文件名作为参数传递或将名称分隔为空(但POSIX工具很少支持此功能)。
Graeme 2014年

@Graeme-您对可能的失败是正确的,但我已将其修复。
mikeserv 2014年

啊,很好,发现不会/./在路径中的其他任何地方产生序列。我会记住这个把戏。我认为您可以在之后添加反斜杠,c因为这不是正则表达式的一部分。
Graeme 2014年

0

从您的根目录:

find . -type f | wc -l

您可以将路径(在此处。)更改为要在其中计算文件的目录。如果您不想进入子目录,请添加选项 -maxdepth 1


或从任何目录,find / -type f ...
fedorqui

find没有精确的工作目录的表格不是posix
Kiwy 2014年

我确实忘了加点,我改正了(错字)。
Laurent C.

这将不起作用,因为文件名可以包含换行符。
Anthon 2014年

1
@JennyD还是-printf "\n",也许……
Graeme
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.