import fs from 'fs'; import path from 'path' import crypto from 'crypto'; class FileChecker { private oldFileDir: string; private newFileDir: string; private outDir?: string; private diffFiles: string[]; constructor(oldFileDir: string, newFileDir: string, outDir?: string) { this.oldFileDir = oldFileDir; this.newFileDir = newFileDir; this.outDir = outDir; this.diffFiles = []; } public pickDiff(): void { outDir && this.rmdir(outDir); this.doPickDiff(); } private doPickDiff(filePath: string = ''): void { let newFileFullPath = path.join(this.newFileDir, filePath); let stat = fs.statSync(newFileFullPath); if (stat.isDirectory()) { let childFiles = fs.readdirSync(newFileFullPath); childFiles.map((value: string) => this.doPickDiff(path.join(filePath, value))); } else { let oldFileFullPath = path.join(this.oldFileDir, filePath); if (!fs.existsSync(oldFileFullPath)) { this.copyDiffToOutDir(filePath, '+'); return; } let oldFileStat = fs.statSync(oldFileFullPath); if (oldFileStat.isDirectory()) { this.copyDiffToOutDir(filePath, 'x'); return; } let oldFileMD5 = this.md5(oldFileFullPath); let newFileMD5 = this.md5(newFileFullPath); if (oldFileMD5 !== newFileMD5) { this.copyDiffToOutDir(filePath, 'x'); return; } } } public getDiffFileList(): string[] { return this.diffFiles; } public makeNewOld(): void { this.rmdir(this.oldFileDir); fs.renameSync(this.newFileDir, this.oldFileDir); } private copyDiffToOutDir(filePath: string, type: '-' | '+' | 'x'): void { this.diffFiles.push(`[${type}]${filePath}`); if (this.outDir) { let srcPath = path.join(this.newFileDir, filePath); let outPath = path.join(this.outDir, filePath); this.mkdir(path.dirname(outPath)); fs.copyFileSync(srcPath, outPath); } } private md5(filePath: string): string { let buffer = fs.readFileSync(filePath); let hash = crypto.createHash('md5'); hash.update(buffer); let hex = hash.digest('hex'); return hex; } public rmdir(dir: string): void { if (!fs.existsSync(dir)) return; let files = fs.readdirSync(dir); for (let item of files) { let itemPath = path.join(dir, item); let stat = fs.statSync(itemPath); stat.isDirectory() ? this.rmdir(itemPath) : fs.unlinkSync(itemPath); } fs.rmdirSync(dir); } private mkdir(dir: string): void { if (!fs.existsSync(dir)) { let parentDir = path.dirname(dir); this.mkdir(parentDir); fs.mkdirSync(dir); } } } let cmd = process.argv[2]; let oldDir = process.argv[3]; let newDir = process.argv[4]; let outDir = process.argv[5]; if (oldDir && newDir) { const check = new FileChecker(oldDir, newDir, outDir); switch (cmd) { case 'pick': check.pickDiff(); console.log(`Diff Files:\n${check.getDiffFileList().join('\n')}`); break; case 'move': check.makeNewOld(); console.log(`Move ${newDir} To ${oldDir}`); break; } }