Windows节点中的快速文件夹哈希

Tit*_*tan 7 hash node.js node-webkit

我正在构建一个nodewebkit应用程序,它使本地目录与远程FTP保持同步.要在第一次运行应用程序时构建初始索引,我从远程服务器下载包含所有文件及其文件夹的哈希值的索引文件.然后,我运行此列表并在用户的本地文件夹中查找匹配项.

远程/本地文件夹的总大小可以超过10GB.可以想象,扫描10GB的单个文件可能会非常慢,特别是在普通硬盘(而不是SSD)上.

在节点中是否有一种方法可以有效地获取文件夹的哈希值而无需循环并散列内部的每个单独文件?这样,如果文件夹哈希不同,我可以选择进行昂贵的单个文件检查(一旦我有一个本地索引与远程文件进行比较,我就是这样做的).

hoo*_*nto 2

您可以迭代地遍历目录,统计目录及其包含的每个文件,而不是跟踪链接并生成哈希值。这是一个例子:

'use strict';

// npm install siphash
var siphash = require('siphash');
// npm install walk
var walk = require('walk');

var key = siphash.string16_to_key('0123456789ABCDEF');
var walker  = walk.walk('/tmp', {followLinks: false});

walker.on('directories', directoryHandler);
walker.on('file', fileHandler);
walker.on('errors', errorsHandler); // plural
walker.on('end', endHandler);

var directories = {};
var directoryHashes = [];

function addRootDirectory(name, stats) {
    directories[name] = directories[name] || {
        fileStats: []
    };

    if(stats.file) directories[name].fileStats.push(stats.file);
    else if(stats.dir) directories[name].dirStats = stats.dir;
}

function directoryHandler(root, dirStatsArray, next) {
    addRootDirectory(root, {dir:dirStatsArray});
    next();
}

function fileHandler(root, fileStat, next) {
    addRootDirectory(root, {file:fileStat});
    next();
}

function errorsHandler(root, nodeStatsArray, next) {
    nodeStatsArray.forEach(function (n) {
        console.error('[ERROR] ' + n.name);
        console.error(n.error.message || (n.error.code + ': ' + n.error.path));
    });
    next();
}

function endHandler() {
    Object.keys(directories).forEach(function (dir) {
        var hash = siphash.hash_hex(key, JSON.stringify(dir));
        directoryHashes.push({
            dir: dir,
            hash: hash
        });
    });

    console.log(directoryHashes);
}
Run Code Online (Sandbox Code Playgroud)

当然,您可能希望将其转换为某种命令行应用程序,以便可能接受参数并仔细检查文件是否每次都以正确的顺序返回(也许在散列之前根据文件名对文件统计信息进行排序!) siphash 每次都会返回正确的哈希值。

这不是经过测试的代码..只是为了提供一个示例,说明我可能会从此类事情开始。

编辑:为了减少依赖性,如果您愿意,您可以使用 Node 的加密库而不是 siphash,并且如果您愿意的话,可以require('crypto');自己遍历/统计目录和文件。