NodeJS在目录中递归地散列文件

时间:2015-09-27 16:59:59

标签: node.js recursion hash integrity

我能够在目录中实现递归文件遍历(即浏览目录中的所有子目录和文件)。为此,我在堆栈溢出的相应帖子中使用了answer。其中的片段如下:

var fs = require("fs");

var tree = function(dir, done) {
  var results = {
        "path": dir,
        "children": []
      };
  fs.readdir(dir, function(err, list) {
    if (err) { return done(err); }
    var pending = list.length;
    if (!pending) { return done(null, results); }
    list.forEach(function(file) {
      fs.stat(dir + '/' + file, function(err, stat) {
        if (stat && stat.isDirectory()) {
          tree(dir + '/' + file, function(err, res) {
            results.children.push(res);
            if (!--pending){ done(null, results); }
          });
        } else {
          results.children.push({"path": dir + "/" + file});
          if (!--pending) { done(null, results); }
        }
      });
    });
  });
};

module.exports = tree;

当我跑步时:

 tree(someDirectoryPath, function(err, results) {
        if (err) throw err;

        console.log(results);
      });

我得到了一个示例结果,例如:

{ path: '/Users/UserName/Desktop/1',
  children: 
   [ { path: '/Users/UserName/Desktop/1/file1' },
     { path: '/Users/UserName/Desktop/1/file2' },
     { path: '/Users/UserName/Desktop/1/file3' },
     { path: '/Users/UserName/Desktop/1/subdir1',
       children: [Object] } ] }

我还可以使用fs'来散列特定位置的单个文件。模块ReadStream方法。该片段如下:

/**
 * Checking File Integrity
 */
var fs = require('fs'),
      args = process.argv.splice('2'),
      path = require('path'),
      traverse = require('/Users/UserName/Desktop/tree.js'),
      crypto = require('crypto');
//var algorithm = ['md5', 'sha1', 'sha256', 'sha512'];
var algorithm = 'sha512';
var hashTable = new Array();

        var hash = crypto.createHash(algorithm);

        var fileStream = fs.ReadStream(args[0]);

        fileStream.on('data', function(data) {
                hash.update(data);
        fileStream.on('end', function() {
                var digest = hash.digest('hex');
                console.log('algorithm used: ', algorithm);
                console.log('hash for the file: ',digest);
                hashTable[args[0]] = digest;
                console.log(hashTable);
        });
});

其中args [0]存储ReadStream要读取的文件的位置。对特定文件进行散列后,返回的控制台日志如下:

node fileIntegrityChecker.js hello.txt
algorithm used:  sha512
hash for the file:  9b71d224bd62f3785d96d46ad3ea3d73319bfbc2890caadae2dff72519673ca72323c3d99ba5c11d7c7acc6e14b8c5da0c4663475c2e5c3adef46f73bcdec043
the hashtable is: [ 'hello.txt': '9b71d224bd62f3785d96d46ad3ea3d73319bfbc2890caadae2dff72519673ca72323c3d99ba5c11d7c7acc6e14b8c5da0c4663475c2e5c3adef46f73bcdec043' ]

我的问题我试图以某种方式将树模块功能集成到与哈希相关的js文件中。我的想法是程序将捕获用户的输入,作为目录的路径,并且将处理该输入以遍历文件夹的整个子目录和文件。此外,fileStream.on方法应包含在树模块的回调中。但是我没有在回调机制中完全启动,我希望能从你那里获得一些见解。

这就是我尝试过的

/**
 * Checking File Integrity
 */
var fs = require('fs'),
      args = process.argv.splice('2'),
      path = require('path'),
      tree = require('/Users/UserName/Desktop/tree.js'),
      crypto = require('crypto');
//var algorithm = ['md5', 'sha1', 'sha256', 'sha512'];
var algorithm = 'sha512';
var hashTable = new Array();

        var pathString = 'Users/UserName/Desktop/1';
        tree(pathString, function(err, results) {
            if (err) throw err;

            var hash = crypto.createHash(algorithm);
            var fileStream = fs.ReadStream(results.children[1]['path']);
             fileStream.on('data', function(data) {
                hash.update(data);
             fileStream.on('end', function() {
                var digest = hash.digest('hex');
                console.log('algorithm used: ', algorithm);
                console.log('hash for the file: ',digest);
                hashTable[results.children[1]['path']] = digest;
                console.log('The hashtable is: ', hashTable);
                });
            });
        });

现在,我已经取得了一些进展,因为我没有收到任何错误。基本上我达到了我的范围。 然而我只能显式提取一个结果。出于某种原因,我无法想到如何迭代(例如)获取结果JSON对象的每个子节点。如果这个问题得到解决,我认为问题将彻底解决。

能告诉我一个如何成功组合模块和js文件以递归遍历目录的所有内容并为其中的每个文件创建哈希的方法。我需要这个来根据它们的哈希值最终检查文件中是否发生了一些变化。谢谢!

2 个答案:

答案 0 :(得分:1)

最简单的方法是在您已经遍历目录树时生成哈希。这涉及更新tree.js文件,如下所示:

    } else {
      var fname = dir + "/" + file};
      // put your hash generation here
      generateHash(fname, function (e, hash) {
        if (e) done(e);

        results.children.push({"path": fname, "hash" : hash);
        if (!--pending) { 
          done(null, results); 
        }
      });
    }

然后将您的哈希生成代码放在这样的函数中:

function generateHash (filename, callback) {
    var algorithm = 'sha512';
    var hashTable = new Array();

    var hash = crypto.createHash(algorithm);
    var fileStream = fs.ReadStream(filename);

    fileStream.on('data', function(data) {
        hash.update(data);      
    });
    fileStream.on('end', function() {
        var digest = hash.digest('hex');
        callback(null, digest);
    });
}

答案 1 :(得分:0)

使用vinyl-fs,您可以对目录进行全局化。这可能会减少你的代码。

然后你会通过一个生成哈希的处理程序来管道文件。

以下是一个例子:

fs.src(['./**/*.js'])
  .pipe(hasher)
  .pipe(concater)
  .dest('output.file')