如何在 node.js 中获取目录大小而不递归遍历目录?

Posted

技术标签:

【中文标题】如何在 node.js 中获取目录大小而不递归遍历目录?【英文标题】:How to get directory size in node.js without recursively going through directory? 【发布时间】:2015-08-07 12:06:58 【问题描述】:

如何在 node.js 中获取目录的大小而不递归遍历目录中的所有子项?

例如

var fs = require('fs');
fs.statSync('path/to/dir');

会给我一个这样的对象,

 dev: 16777220,
  mode: 16877,
  nlink: 6,
  uid: 501,
  gid: 20,
  rdev: 0,
  blksize: 4096,
  ino: 62403939,
  size: 204,
  blocks: 0,
  atime: Mon May 25 2015 20:54:53 GMT-0400 (EDT),
  mtime: Mon May 25 2015 20:09:41 GMT-0400 (EDT),
  ctime: Mon May 25 2015 20:09:41 GMT-0400 (EDT) 

size 属性不是目录的大小,而是子目录(也就是其中的文件的总和)。

如果不递归地找到子项的大小(然后将它们相加),就没有办法获得目录的大小(包括其中包含的文件的大小)吗?

我基本上是在尝试做与du -ksh my-directory 等效的操作,但如果给定的目录真的很大(例如/),那么递归获取真正的目录大小需要永远......

【问题讨论】:

我知道du -ksh / 需要很长时间,所以也许这个问题是......静音......我希望我在这里缺少一个 linuxy 的东西...... du 正是这样做的,所以不,你无法绕过它。 据我所知,目录不会跟踪它们下面所有文件的累积大小,因此获得累积大小的唯一方法是递归和添加。这不是一个快速的操作。 【参考方案1】:

我使用这个简单的async/await + fs Promises API (Node.js v14+) 解决方案...它不依赖于外部库或产生新进程,这很好:

const  readdir, stat  = require('fs/promises');

const dirSize = async directory => 
  const files = await readdir( directory );
  const stats = files.map( file => stat( path.join( directory, file ) ) );

  return ( await Promise.all( stats ) ).reduce( ( accumulator,  size  ) => accumulator + size, 0 );

用法:

const size = await dirSize( '/path/to/directory' );
console.log( size );

这不使用任何 循环构造 来递归遍历目录,尽管它是映射/归约数组。其他解决方案只是抽象 NPM 包/C 代码后面的递归,所以应该都很好......

【讨论】:

【参考方案2】:

fast-folder-size 使用 Windows 上的Sysinternals DU 和其他平台上内置的du 程序来快速计算文件夹大小。

安装

npm i fast-folder-size

用法

const fastFolderSize = require('fast-folder-size')

fastFolderSize('.', (err, bytes) => 
  if (err) 
    throw err
  

  console.log(bytes)
)

【讨论】:

【参考方案3】:

您可以在您的目标目录上生成一个du 命令,但正如您所说,第一次它可能会相当慢。你可能不知道du 结果似乎以某种方式被缓存:

$ time du -sh /var
13G /var
du -sh /var  0.21s user 0.66s system 9% cpu 8.930 total
$ time du -sh /var
13G /var
du -sh /var  0.11s user 0.34s system 98% cpu 0.464 total

最初需要 8 秒,然后只需要 0.4 秒

因此,如果您的目录不经常更改,则使用 du 可能是最简单的方法。

另一种解决方案是将其存储在缓存层中,这样您就可以观察根目录的更改,然后计算文件夹的大小,将其存储在缓存中,并在需要时提供服务。要执行此操作,您可以使用 NodeJS 的监视功能,但您会遇到一些跨平台问题,因此像 chokidar 这样的库可能会有所帮助。

【讨论】:

更好的是,您可以使用du -s /var | cut -f1获取以字节为单位的文件夹大小【参考方案4】:

您应该尝试“getFolderSize”节点模块 https://www.npmjs.com/package/get-folder-size

用法

getFolderSize(folder, [regexIgnorePattern], callback)

例子:

var getSize = require('get-folder-size');

getSize(myFolder, function(err, size) 
  if (err)  throw err; 

  console.log(size + ' bytes');
  console.log((size / 1024 / 1024).toFixed(2) + ' Mb');
);

【讨论】:

您好,请扩展您的答案以包含即使没有超链接也有用的解决方案。提前致谢。 您发布的模块使用递归解决方案。 github.com/alessioalex/get-folder-size/blob/master/index.js#L7 对于小的浅目录可能没问题。对于大的深层目录来说是可怕的。我宁愿运行一个 shell 命令并让操作系统处理它。它也没有给出磁盘大小 - 这是检查文件夹大小的常见动机。

以上是关于如何在 node.js 中获取目录大小而不递归遍历目录?的主要内容,如果未能解决你的问题,请参考以下文章

js如何遍历本地目录的文件

javascript [node.js 8+]递归获取目录中的所有文件

如何使用 APFS 在 iOS 10.3 上获取目录的大小?

Node.js如何获取文件大小

帮助我理解中序遍历而不使用递归

如何在 C 中获取目录的大小?