diff --git a/exec/dupefind.js b/exec/dupefind.js index 28e427af673e8dc3ff962b5c24c260019e3d703b..051b908e264ee89076ee6ee072872054032b7c9b 100755 --- a/exec/dupefind.js +++ b/exec/dupefind.js @@ -7,10 +7,11 @@ load("file_size.js"); "use strict"; -var detail = 0; +var detail = FileBase.DETAIL.NORM; var min_size = 1024; var dir_list = []; var exclude = []; +var json_space = 4; var hash_type; var options = {}; for(var i = 0; i < argc; i++) { @@ -29,8 +30,9 @@ for(var i = 0; i < argc; i++) { writeln(" -sha1 search for duplicate SHA-1 sums (the default)"); writeln(" -crc32 search for duplicate CRC-32 sums"); writeln(" -md5 search for duplicate MD5 sums"); - writeln(" -json use JSON formatted output"); - writeln(" -v increase verbosity of output"); + writeln(" -json[=space] create JSON formatted output"); + writeln(" -v increase verbosity of JSON output"); + writeln(" -dedupe remove/delete duplicate files"); exit(0); } if(opt.indexOf("ex=") == 0) { @@ -57,6 +59,11 @@ for(var i = 0; i < argc; i++) { detail++; continue; } + if(opt.indexOf("json=") == 0) { + options.json = true; + json_space = parseInt(opt.slice(5), 10); + continue; + } switch(opt) { case 'crc16': case 'crc32': @@ -93,6 +100,7 @@ for(var i in dir_list) { if(exclude.indexOf(file.name.toUpperCase()) >= 0) continue; file.dir = dir_code; + file.path = base.get_path(file.name); if(options.names) { var fname = file.name.toLowerCase(); if(!name[fname]) @@ -135,16 +143,20 @@ for(var n in hash) { if(options.names) { log(dupe.name.length + " duplicate file names (" + file_size_str(name_bytes,1 , 1) + " bytes)"); - if(options.json) - writeln(JSON.stringify(dupe.name, null, 4)); + if(options.dedupe) + writeln(remove_list(dupe.name, "name") + " files removed"); + else if(options.json) + writeln(JSON.stringify(dupe.name, null, json_space)); else print_list(dupe.name, "name"); } if(hash_type) { log(dupe.hash.length + " duplicate file " + hash_type.toUpperCase() + " sums of at least " + min_size + " bytes (" + file_size_str(hash_bytes, 1, 1) + " bytes)"); - if(options.json) - writeln(JSON.stringify(dupe.hash, null, 4)); + if(options.dedupe) + writeln(remove_list(dupe.hash, hash_type) + " files removed"); + else if(options.json) + writeln(JSON.stringify(dupe.hash, null, json_space)); else print_list(dupe.hash, hash_type); } @@ -152,10 +164,40 @@ if(hash_type) { function print_list(list, key) { for(var i = 0; i < list.length; i++) { - writeln("Duplicate file " + key + " #" + (i + 1) + ": " + list[i][0][key]); + var value = list[i][0][key]; + if(key == 'crc32') + value = format("%08X", value); + writeln("Duplicate file " + key + " #" + (i + 1) + ": " + value); for(var j = 0; j < list[i].length; j++) { - var f = list[i][j]; - writeln(format(" %s%s", file_area.dir[f.dir].path, f.name)); + var file = list[i][j]; + writeln(" " + file.path); + } + } +} + +function remove_list(list, key) +{ + var removed = 0; + for(var i = 0; i < list.length; i++) { + var value = list[i][0][key]; + if(key == 'crc32') + value = format("%08X", value); + writeln("Duplicates of file " + key + " #" + (i + 1) + ": " + value); + writeln(" Keeping " + list[i][0].path); + for(var j = 1; j < list[i].length; j++) { + var file = list[i][j]; + var base = new FileBase(file.dir); + if(!base.open()) { + alert(base.errror); + break; + } + writeln(" Removing " + file.path); + if(base.remove(file.name, /* delete: */true)) + removed++; + else + alert(base.error); + base.close(); } } + return removed; }