我可以在目录中放入多少个文件?


561

我在一个目录中保留多少个文件有关系吗?如果是这样,那么目录中有多少文件太多了,文件太多会有什么影响?(这是在Linux服务器上。)

背景:我有一个相册网站,并且每张上传的图像都被重命名为8位十六进制ID(例如a58f375c.jpg)。这是为了避免文件名冲突(例如,如果上传了许多“ IMG0001.JPG”文件)。原始文件名和任何有用的元数据都存储在数据库中。现在,在images目录中大约有1500个文件。这使得通过FTP或SSH客户端列出目录中的文件需要花费几秒钟的时间。但是我看不到有什么其他效果。特别是,对图像文件提供给用户的速度似乎没有任何影响。

我曾考虑过通过制作16个子目录(0-9和af)来减少图片数量。然后,根据文件名的第一个十六进制数字将图像移动到子目录中。但是我不确定是否有这样做的理由,除了偶尔通过FTP / SSH列出目录之外。

Answers:


736

FAT32

  • 最大文件数:268,173,300
  • 每个目录文件的最大数量:2 16  - 1(65535)
  • 最大文件大小:2 GiB-1(不带LFS),4 GiB-1(带 LFS)

NTFS

  • 最大文件数:2 32  - 1(4,294,967,295)
  • 最大档案大小
    • 实施:2 44  - 2 6个字节(16的TiB - 64 KIB)
    • 理论值:2 64  - 2 6个字节(16 EIB - 64 KIB)
  • 最大卷大小
    • 实施:2 32  - 1簇(256的TiB - 64 KIB)
    • 理论上:2  64-1个群集(1个YiB-64 KiB)

ext2

  • 最大文件数:10 18
  • 每个目录的最大文件数:〜1.3×10 20(超过10,000的性能问题)
  • 最大档案大小
    • 16 GiB(1 KiB的块大小)
    • 256 GiB(块大小为2 KiB)
    • 2 TiB(块大小为4 KiB)
    • 2 TiB(块大小为8 KiB)
  • 最大卷大小
    • 4 TiB(块大小为1 KiB)
    • 8 TiB(块大小为2 KiB)
    • 16 TiB(块大小为4 KiB)
    • 32 TiB(块大小为8 KiB)

ext3

  • 最大文件数:min(volumeSize / 2 13,numberOfBlocks)
  • 最大文件大小:与ext2相同
  • 最大卷大小:与ext2相同

ext4

  • 最大文件数:2 32  - 1(4,294,967,295)
  • 每个目录的最大文件数:无限制
  • 最大文件大小:2 44  - 1个字节(16的TiB - 1)
  • 最大音量大小:2 48  - 1个字节(256的TiB - 1)

24
我假设这些是整个分区而不是目录的最大文件数。因此,该信息对于该问题不是太有用,因为不管使用哪种方法,文件的数量都是相等的(除非您将目录视为文件)。
斯特拉格

19
既然我们现在在2012年,我想是时候弄清楚ext4对子目录数没有任何限制了。最大文件大小也增加到16 TB。此外,文件系统的整体大小可能高达1 EB = 1,048,576 TB。
devsnd 2012年

7
显然,ext3每个目录还具有60,000个文件(或目录或链接)的限制。我找到了解决这个难题的办法。
堆叠

8
我知道是旧答案,但是……当您编写EXT4时 - 最大文件数:2³²-1(4,294,967,295)每个目录中的最大文件数:无限制,您真的很困惑我,因为2³²-1!=“无限制”。我想我现在要喝咖啡。;)尽管如此+1
e-sushi

10
硬文件系统限制无法回答问题“ 我在一个目录中保存多少文件有关系吗?
Etki

191

我在一个ext3目录中有超过800万个文件。,以及该线程中讨论的大多数其他方法readdir()使用的libc 列出大型目录。findls

出现这种情况的原因lsfind速度很慢,因为一次readdir()只能读取32K目录条目,因此在慢速磁盘上,需要多次读取才能列出目录。有解决此速度问题的方法。我在以下位置写了一篇非常详细的文章:http : //www.olark.com/spw/2011/08/you-can-list-a-directory-with-8-million-files-but-not-with- ls /

取得的关键是:getdents()直接使用-http: //www.kernel.org/doc/man-pages/online/pages/man2/getdents.2.html,而不是基于libc的任何东西,readdir()因此您可以指定缓冲区从磁盘读取目录条目时的大小。


6
有趣的阅​​读!请问在什么情况下一个目录中有800万个文件?哈哈
Aᴄʜᴇʀᴏɴғᴀɪʟ

我也一样 我已经迁移了表的Blob列,我已将每个Blob列导出为文件。大约有800万个文件:)

65

我有一个包含88,914个文件的目录。像您一样,它用于在Linux服务器上存储缩略图。

是的,通过FTP或php函数列出的文件比较慢,是的,但是在显示文件时也会降低性能。例如www.website.com/thumbdir/gh3hg4h2b4h234b3h2.jpg的等待时间为200-400毫秒。作为另一个网站上的比较,我在目录中大约有100个文件,等待约40毫秒后才显示图像。

我给出了这个答案,因为大多数人都已经写了目录搜索功能的执行方式,您不会在thumb文件夹上使用它-只是静态地显示文件,但是会对文件实际使用方式的性能感兴趣。


6
这是唯一有用的答案。我们也有类似的经历。我们的限制是1.000个文件,以减少备份问题(太多的目录也会减慢速度)。
mgutt 2012年

1
它可以是有用的安装与驱动noatime的还有:howtoforge.com/...和阅读,也:serverfault.com/questions/354017/...
mgutt

2
您正在使用什么文件系统来减慢速度?例如,XFS应该能够轻松处理目录中的100,000个文件,而不会出现明显的速度下降。
伊桑(Ethan)

1
与大多数其他人的看法相反,我想确认这个答案。我们的社交网络网站上有数十万张图片。为了提高性能,我们被迫拥有100个子目录(对于某些文件为1000个)子目录,并将文件分发到其中(对于Linux + Apache,我们使用ext3)。
wmac

57

它在某种程度上取决于Linux服务器上使用的特定文件系统。如今,默认值为带有dir_index的ext3,这使得搜索大型目录变得非常快。

因此,除了您已经提到的速度之外,速度不应该成为问题,因为上市将需要更长的时间。

一个目录中的文件总数是有限制的。我似乎记得它肯定可以处理32000个文件。


4
Gnome和KDE以极快的速度加载大目录,Windows会缓存该目录,以使其合理。我喜欢Linux,但是kde和gnome的编写不佳。
rook 2010年

1
ext4似乎默认情况下与dir_index等效。
Falken教授的合同

22
ext3的一个目录中大约有32K个子目录,但是OP在谈论图像文件。启用Dir索引的ext3文件系统中的文件没有限制(实际吗?)。
彼得N·刘易斯

1
这个答案已经过时,如今的默认值是ext4
鲍里斯(Boris)

1
“启用Dir索引的ext3文件系统中的文件没有限制(实际限制)”-我刚启用4TB ext4文件系统上的目录中的文件空间就用光了dir_index。我的目录中有大约1700万个文件。答案是large_dir使用tune2fs 打开。
lunixbochs

49

请记住,在Linux上,如果目录中包含太多文件,则外壳程序可能无法扩展通配符。我在Linux上托管的相册遇到此问题。它将所有调整大小的图像存储在一个目录中。虽然文件系统可以处理许多文件,但Shell无法。例:

-shell-3.00$ ls A*
-shell: /bin/ls: Argument list too long

要么

-shell-3.00$ chmod 644 *jpg
-shell: /bin/chmod: Argument list too long

33
@Steve,在这些情况下,请使用find(1)和/或xargs(1)。出于同样的原因,最好在脚本中使用此类工具,而不要使用命令行扩展。
Dave C

3
@Steve,当文件夹中文件的数量增加时,您是否发现性能下降?还是没有关系?
Pacerier 2012年

6
这是一个很好的观点,但是对于nitpick,给出的原因是错误的。该参数列表太长不是外壳的限制,但该系统的的exec实现。Shell通常可以很好地扩展通配符-调用exec具有这么多参数的函数会返回错误。
2012年

昨晚(Fedora 15),我在目录中有大约40万个文件,并使用“ rm”(somefiles *)遇到了相同的错误。我可以使用“查找”将较旧的文件修剪到可以使用通配符“ rm”的程度。
PJ Brunet

10.000.000文件到etx4上的目录工作正常。访问时不会对性能造成太大影响。但是使用通配符会比较慢。使用喜欢对文件名进行排序的shell程序时要小心!:)
西蒙·里杰(SimonRigét)

25

我正在研究类似的问题。我们有一个分层的目录结构,并使用图像ID作为文件名。例如,将的图片id=1234567放置在

..../45/67/1234567_<...>.jpg

使用最后4位数字确定文件的位置。

对于几千个图像,您可以使用一个一级的层次结构。我们的系统管理员建议在任何给定目录(ext3)中添加不超过数千个文件,以提高效率/备份/他想到的其他原因。


1
这是一个很好的解决方案。如果您坚持使用2位数细分,则到文件的目录的每个级别最多将包含100个条目,而最底部的目录将只有1个文件。
RobKohr '15


21

我只需要在ext4文件系统中创建一个目录,其中包含1,000,000个文件,然后通过Web服务器随机访问这些文件即可。我没有注意到访问超过(例如)那里只有10个文件的文件的任何溢价。

这与几年前的经验完全不同ntfs


什么样的文件?文字或图片?我在ext4上,必须在wordpress下的单个目录中导入80000张图片,并且想知道它是否可以
Yvon Huynh

1
@YvonHuynh:文件的类型是完全不相关的。列出/跟踪文件的目录中的开销是相同的。
TJ Crowder

14

我遇到的最大问题是在32位系统上。一旦传递了一定数量,“ ls”之类的工具就会停止工作。

一旦通过该障碍,尝试对该目录执行任何操作将成为一个巨大的问题。


9

我一直遇到同样的问题。试图在ext4的Ubuntu服务器中存储数百万个文件。结束了运行自己的基准测试。发现平面目录在使用更简单的同时性能更好:

基准

写了一篇文章


欢迎使用指向解决方案的链接,但是请确保没有该链接的情况下,您的回答是有用的:在链接周围添加上下文,以便您的其他用户可以了解它的含义和含义,然后引用您所使用页面中最相关的部分如果目标页面不可用,请重新链接。只是链接的答案可能会被删除。
塞缪尔·刘

1
有趣。我们发现,即使在10,000个文件之后,性能也会非常迅速地下降到无法使用的地步。我们决定将文件分成每个级别约100个子目录,以实现最佳性能。我想这个故事的寓意是始终根据自己的要求为自己在自己的系统上进行基准测试。
约书亚·品特

7

如果实现目录分区方案所花费的时间很少,那么我赞成这样做。首次调试涉及通过控制台操作10000文件目录的问题时,您会了解。

例如,F-Spot将照片文件存储为YYYY \ MM \ DD \ filename.ext,这意味着在手动操作〜20000张照片集时我必须处理的最大目录约为800个文件。这也使文件更易于从第三方应用程序浏览。永远不要以为您的软件是访问软件文件的唯一方法。


6
我建议不要按日期进行分区,因为批量导入可能会在特定日期将文件聚类。
最大

好点。在选择分区方案之前,您绝对应该考虑您的用例。我碰巧会以相对广泛的分布来导入照片,而且当我想在F-Spot日期以外操作照片时,找到照片是最简单的方法,因此对我来说是双赢。
Sparr

7

它绝对取决于文件系统。许多现代文件系统使用体面的数据结构来存储目录的内容,但是较旧的文件系统通常只是将条目添加到列表中,因此检索文件是O(n)操作。

即使文件系统做对了,列出目录内容的程序也绝对有可能弄乱并进行O(n ^ 2)排序,因此,为了安全起见,我总是会限制每个文件的数量。目录不超过500。


7

它实际上取决于所使用的文件系统以及一些标志。

例如,ext3可以有成千上万个文件。但是经过数千次之后,它过去的运行速度非常慢。通常在列出目录时,但在打开单个文件时。几年前,它获得了“ htree”选项,从而大大缩短了获得给定文件名的索引节点所需的时间。

就个人而言,我使用子目录将大多数级别保持在一千个左右。在您的情况下,我将创建256个目录,并使用ID的最后两个十六进制数字。使用最后一位而不是第一位,这样可以使负载平衡。


6
如果文件名是完全随机的,则使用哪个数字都没有关系。
斯特拉格

实际上,这些文件名是随机生成的。
基普(Kip)

2
或使用文件名SHA-1摘要的前N个字节。
gawi 2015年

6

ext3实际上确实有目录大小限制,并且它们取决于文件系统的块大小。没有每个目录的“最大数量”的文件,而是每个目录的“用于存储文件条目的最大块的数量”。具体来说,目录本身的大小不能超过高度为3的b树,并且树的扇出取决于块大小。有关更多详细信息,请参见此链接。

https://www.mail-archive.com/cwelug@googlegroups.com/msg01944.html

最近,我在一个以2K块格式化的文件系统上被这个问题咬住了,warning: ext3_dx_add_entry: Directory index full!当我从另一个ext3文件系统复制时,该文件系统莫名其妙地得到了目录已满的内核消息。就我而言,只有480,000个文件的目录无法复制到目标位置。


5

问题归结于您将如何处理文件。

在Windows下,任何文件超过2k的目录都倾向于在资源管理器中为我缓慢打开​​。如果它们都是图像文件,则在缩略图视图中打开超过1k的速度会非常缓慢。

一次,系统施加的限制为32,767。现在更高了,但即使在大多数情况下,一次也无法处理太多文件。


5

上面大多数答案无法显示的是,原始问题没有“一刀切”的答案。

在当今的环境中,我们拥有由不同硬件和软件组成的大型企业集团-有些是32位的,有些是64位的,有些是最先进的,有些是经过实践检验的-可靠且永不改变。除此之外,还包括各种较旧和较新的硬件,较旧和较新的OS,不同的供应商(Windows,Unix,Apple等)以及许多实用程序和服务器。随着硬件的改进以及软件已转换为64位兼容性,在使这个非常大而复杂的世界中的所有部分都能够顺应快速变化的步伐时,必须要有相当大的延迟。

恕我直言,没有一种方法可以解决问题。解决方案是研究可能性,然后通过反复试验找到最适合您特定需求的方法。每个用户都必须确定哪种方法适用于他们的系统,而不是使用Cookie切割器方法。

例如,我有一台带有几个非常大文件的媒体服务器。结果只有大约400个文件填充3 TB驱动器。仅使用了1%的inode,但使用了总空间的95%。拥有很多较小文件的其他人可能会在索引节点接近填充空间之前用尽它们。(通常,在ext4文件系统上,每个文件/目录使用1个inode。)虽然理论上目录中可能包含的文件总数几乎是无限的,但实用性决定了整体使用率决定了实际单位,而不是只是文件系统功能。

我希望上述所有不同的答案能促进思想和问题的解决,而不是为进步提出不可逾越的障碍。


4

我记得运行了一个在输出中创建大量文件的程序。文件在每个目录中的排序为30000。我不记得必须重用产生的输出时遇到任何读取问题。它在32位Ubuntu Linux笔记本电脑上,即使几秒钟后Nautilus仍显示目录内容。

ext3文件系统:在64位系统上,类似的代码可以很好地处理每个目录64000个文件。


4

“取决于文件系统”
一些用户提到性能影响取决于所使用的文件系统。当然。像EXT3这样的文件系统可能非常慢。但是,即使你使用EXT4或者XFS你不能阻止通过上市文件夹lsfind或通过像FTP外部连接会越来越慢的慢。

解决方案
我更喜欢使用@armandino的方法。为此,我在PHP中使用此小功能将ID转换为一个文件路径,每个目录可生成1000个文件:

function dynamic_path($int) {
    // 1000 = 1000 files per dir
    // 10000 = 10000 files per dir
    // 2 = 100 dirs per dir
    // 3 = 1000 dirs per dir
    return implode('/', str_split(intval($int / 1000), 2)) . '/';
}

或者,如果您想使用字母数字字符,则可以使用第二个版本:

function dynamic_path2($str) {
    // 26 alpha + 10 num + 3 special chars (._-) = 39 combinations
    // -1 = 39^2 = 1521 files per dir
    // -2 = 39^3 = 59319 files per dir (if every combination exists)
    $left = substr($str, 0, -1);
    return implode('/', str_split($left ? $left : $str[0], 2)) . '/';
}

结果:

<?php
$files = explode(',', '1.jpg,12.jpg,123.jpg,999.jpg,1000.jpg,1234.jpg,1999.jpg,2000.jpg,12345.jpg,123456.jpg,1234567.jpg,12345678.jpg,123456789.jpg');
foreach ($files as $file) {
    echo dynamic_path(basename($file, '.jpg')) . $file . PHP_EOL;
}
?>

1/1.jpg
1/12.jpg
1/123.jpg
1/999.jpg
1/1000.jpg
2/1234.jpg
2/1999.jpg
2/2000.jpg
13/12345.jpg
12/4/123456.jpg
12/35/1234567.jpg
12/34/6/12345678.jpg
12/34/57/123456789.jpg

<?php
$files = array_merge($files, explode(',', 'a.jpg,b.jpg,ab.jpg,abc.jpg,ddd.jpg,af_ff.jpg,abcd.jpg,akkk.jpg,bf.ff.jpg,abc-de.jpg,abcdef.jpg,abcdefg.jpg,abcdefgh.jpg,abcdefghi.jpg'));
foreach ($files as $file) {
    echo dynamic_path2(basename($file, '.jpg')) . $file . PHP_EOL;
}
?>

1/1.jpg
1/12.jpg
12/123.jpg
99/999.jpg
10/0/1000.jpg
12/3/1234.jpg
19/9/1999.jpg
20/0/2000.jpg
12/34/12345.jpg
12/34/5/123456.jpg
12/34/56/1234567.jpg
12/34/56/7/12345678.jpg
12/34/56/78/123456789.jpg
a/a.jpg
b/b.jpg
a/ab.jpg
ab/abc.jpg
dd/ddd.jpg
af/_f/af_ff.jpg
ab/c/abcd.jpg
ak/k/akkk.jpg
bf/.f/bf.ff.jpg
ab/c-/d/abc-de.jpg
ab/cd/e/abcdef.jpg
ab/cd/ef/abcdefg.jpg
ab/cd/ef/g/abcdefgh.jpg
ab/cd/ef/gh/abcdefghi.jpg

如您所见$int-version版本,每个文件夹最多包含1000个文件和99个目录,其中包含1000个文件和99个目录...

但是请不要忘记,这会对许多目录造成相同的性能问题!

最后,您应该考虑如何减少文件总数。根据您的目标,您可以使用CSS Sprite组合多个小图像,例如化身,图标,表情符号等。或者,如果您使用许多小的非媒体文件,请考虑以JSON格式进行组合。以我为例,我有数千个小型缓存,最后我决定将它们组合成10个一包。


3

我认为这不能完全回答您有多少个问题,但是解决长期问题的一个想法是,除了存储原始文件元数据之外,还要存储磁盘上存储的文件夹-规范化删除那部分元数据。一旦文件夹的大小超出限制,无论是出于性能,美观还是其他原因,您都可以使用它,您只需创建第二个文件夹并开始将文件放到那里...


3

我遇到了类似的问题。我试图访问其中包含超过10,000个文件的目录。构建文件列表并在任何文件上运行任何类型的命令都花费了太长时间。

我想出了一些PHP脚本来为自己完成此操作,并试图找到一种防止它在浏览器中超时的方法。

以下是我为解决该问题而编写的php脚本。

列出目录中包含FTP文件过多的文件

它如何帮助某人


1

不是答案,而是一些建议。

选择一个更合适的FS(文件系统)。从历史的角度来看,您的所有问题都非常明智,可以成为数十年来不断发展的FS的中心。我的意思是,更现代的FS可以更好地支持您的问题。首先根据FS清单的最终目的制作一个比较决策表。

我认为是时候改变您的范式了。因此,我个人建议使用支持分布式系统的FS,这对大小,文件数量等没有任何限制。否则,您迟早会遇到新的无法预料的问题。

我不确定是否可以工作,但是如果您不提及一些实验,请尝试对当前文件系统使用AUFS。我猜它具有将多个文件夹模拟为单个虚拟文件夹的功能。

要克服硬件限制,可以使用RAID-0。


1

只要没有超出操作系统的限制,就没有一个“太多”的数字。但是,无论操作系统是什么,目录中的文件越多,访问任何单个文件所花费的时间就越长,并且在大多数操作系统上,性能是非线性的,因此,从10,000个文件中查找一个文件所花费的时间长于10倍。然后找到1,000个文件。

与目录中包含许多文件相关的次要问题包括通配符扩展失败。为了降低风险,您可以考虑按上传日期或其他一些有用的元数据对目录进行排序。

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.