NodeJS将一个目录中的所有文件连接起来

12

使用NodeJS,是否有更快或更简洁的方式来连接位于目录中的所有文件?

在bash中,我可以这样做:

for file in $1
do
  cat "$file"
  echo
done > $2;

这是我现在正在做的:

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

module.exports = function(directory, destination) {
    return new Promise((resolve, reject) => {
        fs.readdir(directory, (err, files) => {
            if (err) {
                return reject(err);
            }

            (function next() {
                var file = files.shift();
                if (!file) {
                    return resolve();
                }

                fs.readFile(directory + '/' + file, (err, content) => {
                    if (err) {
                        return reject(err);
                    }

                    fs.appendFile(destination, '\n' + content, (err) => {
                        if (err) {
                            return reject(err);
                        }

                        return next();
                    });
                });
            })();
        });
    });
};

我可以问一下这个代码在编写时或者运行时的效率吗? - Jokester
2
你有没有考虑过在“并行”中运行承诺(promises)? - Pratik Gaikwad
@PratikGaikwad 谢谢建议。是的,我会这样做 :) 只是想知道是否有比这更推荐的方法。 - d-_-b
是的。并行执行将使运行更快。而Nodejs有一种更有效的处理线程的方式。我一旦从我的计算机登录,就会放入代码。 - Pratik Gaikwad
在bash中,您甚至可以像这样简单地执行它:cat ./* > merged-content-of-all-files - dcts
5个回答

21
require('child_process').execSync('cat *').toString('UTF-8')

:D


不错不错! :D - vintagexav
6
只能在基于Unix的系统上使用,因为在PowerShell中“cat”的意思完全不同。 - Alex Stacks

4
使用 async 库,您可以轻松地并行读取文件,然后将结果合并。
const fs = require("fs");
const async = require("async");
const path = require("path");

module.exports = function(directory, destination) {

  return new Promise((resolve, reject) => {

    fs.readdir(directory, (err, files) => {
        if (err)
            return reject(err);

        files = files.map(file => path.join(directory,file));

        //Read all files in parallel
        async.map(files, fs.readFile, (err, results) => {
            if (err)
                return reject(err);

           //results[0] contents of file #1
           //results[1] contents of file #2
           //results[n] ...

            //Write the joined results to destination
            fs.writeFile(destination, results.join("\n"), (err) => {
                if (err)
                    return reject(err);

                resolve();
            });
        });

    });
  });
}

4
如果您要使用bluebird,那么您就可以享受到promisification的好处。您可以使用promisifyAll()将接受错误回调的fs模块中所有异步函数转换为返回promise的形式。您可以在上面的promisification链接中了解更多信息。
以下代码将所有文件读取为字符串,然后将它们的内容减少为一个单一的字符串,并将该字符串写入destination中。
最好不要在此处catch()任何返回的错误。相反,调用者应该附加一个catch()来处理他们需要的任何返回的错误。
const Promise = require('bluebird')
const fs = Promise.promisifyAll(require('fs'))
const path = require('path')

module.exports = (directory, destination) => {
  return fs.readdirAsync(directory)
    .map(file => fs.readFileAsync(path.join(directory, file), 'utf8'))
    .then(contents => fs.writeFileAsync(destination, contents.join('\n')))
}

3

一行代码实现读取目标文件夹内所有文件内容并写入目标文件:

fs.readdirSync('替换为目标文件夹路径').forEach((file) => { if(fs.lstatSync(file).isFile()) fs.appendFileSync('替换为目标文件路径', fs.readFileSync(file).toString()) })

将 './' 替换为目标文件夹路径,将 './output.file' 替换为目标文件路径。


1
同时,在 lstatSync 和 readFileSync 的“file”参数中必须指定路径。 - EdoB

1

您可以在没有bluebird的情况下完成相同的事情,因为node 8.X包括util包来promisify fs API。

这个例子展示了我如何在我的项目中使用它来连接最小化的文件(如果需要,可以删除过滤器)。

You can do the same thing without bluebird , since node 8.X includes the util package to promisify fs API.

This exemple shows how i use it in my project to concatenate minified files (so remove the filter if necessary).


const {promisify} = require("util");  //requires node 8.X
const readdir = promisify(fs.readdir);
const readFile = promisify(fs.readFile);
const appendFile = promisify(fs.appendFile);


// Append all minified and obsfucated files in source directory
// The resulting file is generated in destination
function appendFile(directory, destination) {
 readdir(directory)
  .then((files) => {
   console.log('FILES CONTENT:', files);
   files.filter(file => {
    console.log('FILTER > ' + file);
    return (file.indexOf('-min.js') != -1 && file.indexOf('-min.js.map') == -1) 
   })
   .map(file => {
    console.log('MAP ('+destination+') > ' + path.join(directory, file));
    readFile(path.join(directory, file), 'utf8')
    .then(data => {
     //console.log('DATA:', data);
     appendFile(destination, data+'\n')
     .then(() => {
      console.log('append done');
     })
     .catch((err) => {
      displayError(err);
     });
    });
   });
  })
  .catch((err) => {
   console.log('ERROR:', err);
   displayError(err);
  });
}


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接