Created
September 16, 2012 15:04
-
-
Save hanji/3732767 to your computer and use it in GitHub Desktop.
bulk file renaming utility
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// rename.js --- bulk file renaming utility (like *nix rename.pl) | |
// (c) Copyright 2012, Ji Han (hanji <at> outlook <dot> com) | |
// you are free to distribute it under the BSD license. | |
if (!Array.prototype.map) Array.prototype.map = function (f, t){ | |
var o = Object(this); | |
var r = new Array(o.length >>> 0); | |
for (var i = 0; i < r.length; ++i){ if (i in o) r[i] = f.call(t, o[i], i, o) } | |
return r; | |
}; | |
if (!Array.prototype.filter) Array.prototype.filter = function (f, t){ | |
var o = Object(this); | |
var N = o.length >>> 0; | |
var r = []; | |
for (var i = 0; i < N; ++i){ | |
if (i in o){ | |
var v = o[i]; | |
if (f.call(t, v, i, o)) r.push(v); | |
} | |
} | |
return r; | |
}; | |
if (!String.prototype.reverse) String.prototype.reverse = function (){ | |
return this.split('').reverse().join(''); | |
}; | |
/// main | |
(function (){ | |
if (WScript.Arguments.Length == 0){ | |
WScript.Echo('rename "<operator>/<pattern>/<string>/[<modifiers>]" [-f] [-r] [-d <maxdepth>] [<files>]'); | |
WScript.Quit(1); | |
} | |
var fso = new ActiveXObject('Scripting.FileSystemObject'); | |
// folder is a Folder object [e.g. from fso.GetFolder()] | |
// fn is a function which operates on File/Folder object | |
var recurseFolder = function (folder, fn, depth, maxdepth){ | |
if (folder.Files){ | |
for (var e = new Enumerator(folder.Files); !e.atEnd(); e.moveNext()){ | |
fn(e.item()) | |
} | |
} | |
if (folder.Subfolders){ | |
for (var e = new Enumerator(folder.SubFolders); !e.atEnd(); e.moveNext()){ | |
fn(e.item()); | |
if (depth < maxdepth){ arguments.callee(e.item(), fn, depth + 1, maxdepth) } | |
} | |
} | |
} | |
// expand wildcards (asterisk [*] and question mark [?]) recursively | |
// given path may be relative, and may contain environment variables. | |
// but wildcards only work for the filename part of a path. | |
// return an array of full paths of matched files. | |
// {{{ | |
var expandWildcardsRecursively = function (n, md){ | |
var pattern = fso.GetFileName(n); | |
// escape regex metacharacters (except \, /, * and ?) | |
// \ and / wouldn't appear in filename | |
// * and ? are treated as wildcards | |
pattern = pattern.replace(/([\[\](){}^$.+|-])/g, '\\$1'). | |
replace(/\*/g, '.*'). // * matches zero or more characters | |
replace(/\?/g, '.'). // ? matches one character | |
replace(/^(.*)$/, '\^$1\$'); // matches the whole filename | |
var re = new RegExp(pattern, 'i'); // case insensitive | |
var folder = fso.GetFolder(fso.GetParentFolderName(fso.GetAbsolutePathName(n))); | |
var l = []; | |
recurseFolder(folder, function (i){ if (i.Name.match(re)) l.push(i.Path) }, 0, md); | |
return l; | |
} | |
// }}} | |
// parse "<operator>/<pattern>/<string>/[<modifiers>]" | |
// return an array splitted at unescaped forward slashes | |
// {{{ | |
var parseExpr = function (s){ | |
return s.reverse(). // reverse the string | |
split(/\/(\\\\)*(?!\\)/). // split at unescaped forward slashes | |
filter(function(x){return x}). // filter out 'undefined' | |
map(function(x){return x.reverse()}). // reverse each element | |
reverse(); // reverse array | |
} | |
// }}} | |
var expr = WScript.Arguments(0) + 'i'; | |
var args = []; | |
var options = {}; | |
for (var i = 1; i < WScript.Arguments.Length; ++i){ | |
if (WScript.Arguments(i).substring(0, 1) != '-'){ | |
args.push(WScript.Arguments(i)); | |
} else if (WScript.Arguments(i) == '-f'){ | |
options['fullpath'] = true; | |
} else if (WScript.Arguments(i) == '-r'){ | |
options['recursive'] = true; | |
} else if (WScript.Arguments(i) == '-d'){ | |
options['maxdepth'] = WScript.Arguments(++i); | |
} else if (WScript.Arguments(i) == '--'){ | |
continue; | |
} else { | |
WScript.Echo('invalid option \'' + WScript.Arguments(i) +'\''); | |
WScript.Quit(1); | |
} | |
} | |
if (options['maxdepth']){ | |
var md = options['maxdepth']; | |
} else if (options['recursive']){ | |
var md = 1<<31>>>0; | |
} else { | |
var md = 0; | |
} | |
var tokens = parseExpr(expr); | |
if (tokens.length != 4){ | |
WScript.Echo('error parsing expression \'' + expr + '\'.'); | |
WScript.Quit(1); | |
} | |
if (tokens[0] != 's'){ | |
WScript.Echo('<operator> must be s.'); | |
WScript.Quit(1); | |
} | |
var pattern = tokens[1]; | |
var substr = tokens[2]; | |
var modifiers = tokens[3]; | |
var re = new RegExp(pattern, modifiers); | |
for (var i = 0; i < args.length; ++i){ | |
var l = expandWildcardsRecursively(args[i], md); | |
for (var j = 0; j < l.length; ++j){ | |
var original = l[j]; | |
if (options['fullpath']){ | |
var nouveau = original.replace(re, substr); | |
} else { | |
var nouveau = fso.GetParentFolderName(original) + '\\' + fso.GetFileName(original).replace(re, substr); | |
} | |
if (nouveau != original){ | |
(fso.FileExists(original) && fso.GetFile(original) || fso.GetFolder(original)).Move(nouveau) | |
} | |
} | |
} | |
})(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment