Node.js: Compare directory contents with file checksums asynchronously
sha256, checksum, async, await, es6
Comparing the content of two directories binary-safe is a common used feature especially for data synchronization tasks. You can easily implement a simple compare algorithm by generating the sha256 checksums of each file – this is not a high-performance solution but even works on large files!
const _fs = require('fs-magic'); // compare directoy contents based on sha256 hash tables async function compareDirectories(dir1, dir2){ // fetch file lists const [files1, dirs1] = await _fs.scandir(dir1, true, true); const [files2, dirs2] = await _fs.scandir(dir2, true, true); // num files, directories equal ? if (files1.length != files2.length){ throw new Error('The directories containing a different number of files ' + files1.length + '/' + files2.length); } if (dirs1.length != dirs2.length){ throw new Error('The directories containing a different number of subdirectories ' + dirs1.length + '/' + dirs2.length); } // generate file checksums const hashes1 = await Promise.all(files1.map(f => _fs.sha256file(f))); const hashes2 = await Promise.all(files2.map(f => _fs.sha256file(f))); // convert arrays to objects filename=>hash const lookup = {}; for (let i=0;i<hashes2.length;i++){ // normalized filenames const f2 = files2[i].substr(dir2.length); // assign lookup[f2] = hashes2[i]; } // compare dir1 to dir2 for (let i=0;i<hashes1.length;i++){ // normalized filenames const f1 = files1[i].substr(dir1.length); // exists ? if (!lookup[f1]){ throw new Error('File <' + files1[i] + '> does not exist in <' + dir2 + '>'); } // hash valid ? if (lookup[f1] !== hashes1[i]){ throw new Error('File Checksum of <' + files1[i] + '> does not match <' + files2[i] + '>'); } } return true; } await compareDirectories('/tmp/data0', '/tmp/data1');