如何获取目录中文件的总数?

时间:2011-09-23 12:51:15

标签: node.js

如何获取目录中文件的总数?最好的方式?

8 个答案:

答案 0 :(得分:18)

这是一个使用核心Nodejs fs库与异步库相结合的简单解决方案。它是完全异步的,应该像'du'命令一样工作。

var fs = require('fs'),
    path = require('path'),
    async = require('async');

function readSizeRecursive(item, cb) {
  fs.lstat(item, function(err, stats) {
    if (!err && stats.isDirectory()) {
      var total = stats.size;

      fs.readdir(item, function(err, list) {
        if (err) return cb(err);

        async.forEach(
          list,
          function(diritem, callback) {
            readSizeRecursive(path.join(item, diritem), function(err, size) {
              total += size;
              callback(err);
            }); 
          },  
          function(err) {
            cb(err, total);
          }   
        );  
      }); 
    }   
    else {
      cb(err);
    }   
  }); 
}   

答案 1 :(得分:2)

查看node.js File System functions。看起来您可以使用fs.readdir(path, [cb])fs.stat(file, [cb])的组合来列出目录中的文件并将其大小相加。

这样的事情(完全未经测试):

var fs = require('fs');
fs.readdir('/path/to/dir', function(err, files) {
  var i, totalSizeBytes=0;
  if (err) throw err;
  for (i=0; i<files.length; i++) {
    fs.stat(files[i], function(err, stats) {
      if (err) { throw err; }
      if (stats.isFile()) { totalSizeBytes += stats.size; }
    });
  }
});
// Figure out how to wait for all callbacks to complete
//   e.g. by using a countdown latch, and yield total size
//   via a callback.

请注意,此解决方案仅考虑直接存储在目标目录中的纯文件,并且不执行递归。通过检查stats.isDirectory()并输入,自然会出现递归解决方案,尽管它可能会使“等待完成”步骤变得复杂。

答案 2 :(得分:2)

我测试了以下代码,它运行得很好。 如果您有任何不明白的地方,请告诉我。

var util  = require('util'),
spawn = require('child_process').spawn,
size    = spawn('du', ['-sh', '/path/to/dir']);

size.stdout.on('data', function (data) {
  console.log('size: ' + data);
});


// --- Everything below is optional ---

size.stderr.on('data', function (data) {
  console.log('stderr: ' + data);
});

size.on('exit', function (code) {
  console.log('child process exited with code ' + code);
});

Courtesy Link

第二种方法:

var util = require('util'), exec = require('child_process').exec, child;
child = exec('du -sh /path/to/dir', function(error, stdout, stderr){
    console.log('stderr: ' + stderr);
    if (error !== null){
        console.log('exec error: ' + error);
    }
});

您可能想要引用child_process

的Node.js API

答案 3 :(得分:2)

使用du:https://www.npmjs.org/package/du

require('du')('/home/rvagg/.npm/', function (err, size) {
  console.log('The size of /home/rvagg/.npm/ is:', size, 'bytes')
})

答案 4 :(得分:1)

ES6变体:

import path_module from 'path'
import fs from 'fs'

// computes a size of a filesystem folder (or a file)
export function fs_size(path, callback)
{
    fs.lstat(path, function(error, stats)
    {
        if (error)
        {
            return callback(error)
        }

        if (!stats.isDirectory())
        {
            return callback(undefined, stats.size)
        }

        let total = stats.size

        fs.readdir(path, function(error, names)
        {
            if (error)
            {
                return callback(error)
            }

            let left = names.length

            if (left === 0)
            {
                return callback(undefined, total)
            }

            function done(size)
            {
                total += size

                left--
                if (left === 0)
                {
                    callback(undefined, total)
                }
            }

            for (let name of names)
            {
                fs_size(path_module.join(path, name), function(error, size)
                {
                    if (error)
                    {
                        return callback(error)
                    }

                    done(size)
                })
            }
        }) 
    })
}

答案 5 :(得分:0)

'use strict';

const async = require('async');
const fs    = require('fs');
const path  = require('path')

const getSize = (item, callback) => {
  let totalSize = 0;

  fs.lstat(item, (err, stats) => {
    if (err) return callback(err);

    if (stats.isDirectory()) {

      fs.readdir(item, (err, list) => {
        if (err) return callback(err);

        async.each(list, (listItem, cb) => {

          getSize(path.join(item, listItem), (err, size) => {
            totalSize += size;
            cb();
          });

        },
        (err) => {
          if (err) return callback(err);

          callback(null, totalSize);
        });

      });

    } else {
     // Ensure fully asynchronous API
      process.nextTick(function() {
        callback(null, (totalSize += stats.size))
      });
    }

  });

}

getSize('/Applications', (err, totalSize) => { if (!err) console.log(totalSize); });

答案 6 :(得分:0)

我知道我还不算很晚,但是我虽然将我的解决方案包括在内,该解决方案使用基于@maerics答案的promise:

const fs = require('fs');
const Promise = require('bluebird');

var totalSizeBytes=0;

fs.readdir('storage', function(err, files) {
    if (err) throw err;

    Promise.mapSeries(files, function(file){
        return new Promise((resolve, reject) => {
            fs.stat('storage/' + file,function(err, stats) {
                if (err) { throw err; }
                if (stats.isFile()) { totalSizeBytes += stats.size; resolve(); }
            });
        })
    }).then(()=>{
        console.log(totalSizeBytes);
    });

});

答案 7 :(得分:0)

function readSizeRecursive(folder, nested = 0) {
  return new Promise(function(resolve, reject) {
    const stats = fs.lstatSync(path.resolve(__dirname, '../projects/', folder));
    var total = stats.size;
    const list = fs.readdirSync(path.resolve(__dirname, '../projects/', folder));
    if(list.length > 0){
      Promise.all(list.map(async li => {
        const stat = await fs.lstatSync(path.resolve(__dirname, '../projects/', folder, li));
        if(stat.isDirectory() && nested == 0){
          const tt = await readSizeRecursive(folder, 1);
          total += tt;
        } else {
          total += stat.size;
        }
      })).then(() => resolve(convertBytes(total)));
    } else {
      resolve(convertBytes(total));
    }
  });
}

const convertBytes = function(bytes) {
  const sizes = ["Bytes", "KB", "MB", "GB", "TB"]

  if (bytes == 0) {
    return "n/a"
  }

  const i = parseInt(Math.floor(Math.log(bytes) / Math.log(1024)))

  if (i == 0) {
    return bytes + " " + sizes[i]
  }

  // return (bytes / Math.pow(1024, i)).toFixed(1) + " " + sizes[i]
  return parseFloat((bytes / Math.pow(1024, i)).toFixed(1));
}