求教,怎么用Nodejs异步方式计算一个文件夹下总文件数

求教,怎么用Nodejs异步方式计算一个文件夹下总文件数

如果是同步方式,一个递归很容易解决这个问题,异步方式怎么实现?

同步方式代码:

var fs = require('fs');
var getFileNum = function(fileName) {
 var num = 0;
 var stats = fs.statSync(fileName);
 if (stats.isDirectory()) {
  var files = fs.readdirSync(fileName);
  for ( var i = 0; i < files.length; i++) {
   num += getFileNum(fileName + '\\' + files[i]);
  }
 } else if (stats.isFile()) {
  num += 1;
 }
 return num;
}
var num = getFileNum('E:\\');
console.log(num);

8 回复

当然可以。为了使用异步方式计算一个文件夹下的总文件数,我们可以利用Node.js的fs.promises模块来实现。这种方式可以避免阻塞事件循环,从而提高程序的整体性能。

异步版本代码

首先,我们需要将同步的代码转换为基于Promise的异步版本。这可以通过引入fs.promises模块来实现,该模块提供了与fs模块相同的方法,但返回的是Promise对象,这样我们就可以使用.then()async/await语法来处理异步操作。

以下是使用async/await语法的异步代码示例:

const fs = require('fs').promises;
const path = require('path');

const getFileNumAsync = async (dirPath) => {
    try {
        const files = await fs.readdir(dirPath);
        let fileCount = 0;

        for (const file of files) {
            const filePath = path.join(dirPath, file);
            const isDirectory = await fs.stat(filePath);

            if (isDirectory.isDirectory()) {
                fileCount += await getFileNumAsync(filePath);
            } else if (isDirectory.isFile()) {
                fileCount++;
            }
        }

        return fileCount;
    } catch (error) {
        console.error(`Error reading directory: ${error.message}`);
        return 0;
    }
};

(async () => {
    const num = await getFileNumAsync('E:\\');
    console.log(`Total number of files: ${num}`);
})();

解释

  1. 引入模块:

    • fs.promises 提供了异步版本的文件系统方法。
    • path 模块用于处理和转换文件路径。
  2. 定义异步函数:

    • getFileNumAsync 是一个异步函数,它接受一个目录路径作为参数。
    • 使用 await fs.readdir(dirPath) 来异步读取目录中的所有文件和子目录名。
    • 对于每个文件或子目录,使用 await fs.stat(filePath) 来获取其状态信息(是否为文件或目录)。
    • 如果是目录,则递归调用 getFileNumAsync 并累加结果。
    • 如果是文件,则增加计数器 fileCount
  3. 错误处理:

    • 使用 try...catch 结构来捕获并处理可能发生的错误。
  4. 执行函数:

    • 使用立即执行的异步函数 (async () => { ... })() 来启动整个过程,并打印最终的结果。

这种方法不仅保持了代码的清晰性,还确保了异步操作的高效执行。


var exec = require('child_process').exec;

exec('find * -type f | wc -l', function(error, stdout, stderr) {
  console.log(stdout);
})

一楼正解 调用系统命令最省事儿

还是没解决这个问题,只是用系统命令取代的代码实现,如果换个系统,或代码再加点功能,比如说,计算文件夹下所有文件的总行数,这个代码又要全部写了

total=0
cd $1

for dir in `find * -type f`; do
  len=`wc -l < $dir`
  if [ $? -ne 0 ] ; then
    echo "\n \033[32mError: $dir\033[0m\n\n"
  else
    echo "seraching $dir $len"
    total=$(( $total+$len ))
  fi
done

echo "Total Lines: $total"

统计行数可以这么写,每个平台都是有shell命令的,JS要做系统层的脚本还真没有bash顺手。

同意楼上的,干这些事用bash才是正路

这么做是简单,但那怎么兼容不同的操作系统?

为了实现异步方式计算文件夹下的总文件数,可以使用 fs.promisesfs 模块的回调函数。这里提供一个使用 fs.promises 的示例代码,因为它更加直观和现代。

首先,你需要确保 Node.js 版本支持 fs.promises(通常需要 >= 10.0.0)。

示例代码

const fs = require('fs').promises;
const path = require('path');

async function getFileNum(dirPath) {
    let totalFiles = 0;

    const items = await fs.readdir(dirPath);

    for (let item of items) {
        const fullPath = path.join(dirPath, item);
        const stats = await fs.stat(fullPath);

        if (stats.isDirectory()) {
            totalFiles += await getFileNum(fullPath);
        } else if (stats.isFile()) {
            totalFiles += 1;
        }
    }

    return totalFiles;
}

(async () => {
    try {
        const num = await getFileNum('E:\\');
        console.log(`Total number of files: ${num}`);
    } catch (error) {
        console.error("Error:", error.message);
    }
})();

解释

  1. 引入模块

    • 使用 fs.promisespath 模块。
  2. 定义异步函数 getFileNum

    • 函数接收一个目录路径作为参数。
    • 初始化文件计数器 totalFiles
    • 使用 readdir 异步读取目录中的所有文件和子目录。
    • 遍历读取到的每个项目,检查其是否为目录或文件。
    • 如果是目录,则递归调用 getFileNum 并累加返回的文件数。
    • 如果是文件,则增加文件计数器。
    • 最终返回总的文件数量。
  3. 主程序

    • getFileNum 包装在一个立即执行的异步函数中,以方便使用 await 关键字。
    • 调用 getFileNum 并输出结果。
    • 捕获并处理可能发生的错误。

这样,你就可以通过异步方式计算文件夹下的总文件数了。

回到顶部