Comparing version 0.2.8 to 0.2.9
190
cli.js
@@ -6,8 +6,24 @@ #!/usr/bin/env node | ||
Thing = require("nature").Thing, | ||
presets = require("./lib/preset"), | ||
rename = require("./lib/rename"), | ||
Glob = require("glob").Glob, | ||
log = console.log; | ||
w = require("wodge"), | ||
l = console.log; | ||
function log(success, msg, error){ | ||
l( | ||
"%s %s %s", | ||
success ? w.green(w.symbol.tick) : w.red(w.symbol.cross), | ||
msg, | ||
error ? "(" + w.red(error) + ")" : "" | ||
); | ||
} | ||
function logError(msg){ | ||
l(w.red(msg)); | ||
} | ||
var usage = "Usage: \n\ | ||
$ renamer [--regex] [--find <pattern>] [--replace <string>] [--dry-run] <files>\n\ | ||
$ renamer [--regex] [--find <pattern>] [--replace <string>] [--dry-run] [--verbose] [--name <string>] <files>\n\ | ||
$ renamer --list [--verbose]\n\ | ||
$ renamer --preset <files>\n\ | ||
\n\ | ||
@@ -24,41 +40,57 @@ -f, --find The find string, or regular expression when --regex is set.\n\ | ||
-d, --dry-run Used for test runs. Set this to do everything but rename the file.\n\ | ||
-h, --help Print usage instructions.\n"; | ||
-v, --verbose Use to print additional information.\n\ | ||
-l, --list List the available presets.\n\ | ||
-p, --preset Use the specified preset.\n\ | ||
-n, --name Save the command as a preset with the specified name. \n\ | ||
-h, --help Print usage instructions.\n\ | ||
\n\ | ||
for more detailed instructions, visit https://github.com/75lb/renamer\n"; | ||
function red(txt){ return "\x1b[31m" + txt + "\x1b[0m"; } | ||
function green(txt){ return "\x1b[32m" + txt + "\x1b[0m"; } | ||
function pluck(object, fn){ | ||
var output = []; | ||
for (var prop in object){ | ||
if (fn(object[prop])) output.push(prop); | ||
} | ||
return output; | ||
} | ||
var optionSet; | ||
optionSet = new Thing() | ||
.on("error", function(err){ | ||
log(red("Error: " + err.message)); | ||
logError("Error: " + err.message); | ||
process.exit(1); | ||
}) | ||
.mixIn(new rename.RenameOptions(), "rename") | ||
.define({ | ||
name: "files", | ||
type: Array, | ||
required: true, | ||
defaultOption: true, | ||
groups: ["rename"], | ||
valueFailMsg: "Must supply at least one file, and all must exist" | ||
}) | ||
.define({ name: "dry-run", type: "boolean", alias: "d" }) | ||
.define({ name: "help", type: "boolean", alias: "h" }) | ||
.define({ name: "verbose", type: "boolean", alias: "v" }) | ||
.define("presets", [ | ||
{ name: "name", type: "string", alias: "n", valueTest: /\w+/ }, | ||
{ name: "list", type: "boolean", alias: "l" }, | ||
{ name: "preset", type: "string", alias: "p", valueTest: /\w+/ }, | ||
{ name: "description", type: "string", alias: "x", valueTest: /\w+/ } | ||
]) | ||
.define({ name: "user", type: "string" }) | ||
.set(process.argv); | ||
if (optionSet.help){ | ||
log(usage); | ||
process.exit(0); | ||
function doRename(from, to){ | ||
var newFilenames = [], | ||
logMsg = from + w.green(" -> ") + to; | ||
if (from === to || !to ){ | ||
if (optionSet.verbose) log(false, from); | ||
} else { | ||
if (fs.existsSync(to) || newFilenames.indexOf(to) > -1){ | ||
log(false, logMsg, "file exists"); | ||
} else { | ||
if (!optionSet["dry-run"]) { | ||
try { | ||
fs.renameSync(from, to); | ||
newFilenames.push(to); | ||
log(true, logMsg); | ||
} catch(e){ | ||
log(false, logMsg, e.message); | ||
} | ||
} else { | ||
newFilenames.push(to); | ||
log(true, logMsg); | ||
} | ||
} | ||
} | ||
} | ||
function doWork(files){ | ||
var results, | ||
newFilenames = []; | ||
var results; | ||
@@ -74,3 +106,3 @@ try { | ||
} catch (e){ | ||
log(red(e.message)); | ||
logError(e.message); | ||
process.exit(1); | ||
@@ -80,34 +112,3 @@ } | ||
results.forEach(function(result){ | ||
if (result.before === result.after || !result.after ){ | ||
log("%s: %s", red("no change"), result.before); | ||
} else { | ||
if (fs.existsSync(result.after) || newFilenames.indexOf(result.after) > -1){ | ||
log( | ||
"%s: %s -> %s (%s)", | ||
red("no change"), | ||
result.before, | ||
result.after, | ||
red("file exists") | ||
); | ||
} else { | ||
if (!optionSet["dry-run"]) { | ||
try { | ||
fs.renameSync(result.before, result.after); | ||
newFilenames.push(result.after); | ||
log("%s: %s -> %s", green("rename: "), result.before, result.after); | ||
} catch(e){ | ||
log( | ||
"%s: %s -> %s (%s)", | ||
red("no change"), | ||
result.before, | ||
result.after, | ||
red(e.message) | ||
); | ||
} | ||
} else { | ||
newFilenames.push(result.after); | ||
log("%s: %s -> %s", green("rename: "), result.before, result.after); | ||
} | ||
} | ||
} | ||
doRename(result.before, result.after); | ||
}); | ||
@@ -120,3 +121,2 @@ } | ||
optionSet.files.forEach(function(file){ | ||
if (fs.existsSync(file)){ | ||
@@ -126,5 +126,9 @@ fileList[file] = fs.statSync(file).isDirectory() ? 2 : 1; | ||
var glob = new Glob(file, { sync: true, stat: true }); | ||
glob.found.forEach(function(file){ | ||
fileList[file] = glob.cache[file]; | ||
}); | ||
if (glob.found.length){ | ||
glob.found.forEach(function(file){ | ||
fileList[file] = glob.cache[file]; | ||
}); | ||
} else { | ||
logError("File does not exist: " + file); | ||
} | ||
} | ||
@@ -134,23 +138,57 @@ }); | ||
if (optionSet.valid){ | ||
var noExist = pluck(fileList, function(val){ return val === false; }), | ||
files = pluck(fileList, function(val){ return val === 1; }), | ||
dirs = pluck(fileList, function(val){ return val === 2 || val instanceof Array; }); | ||
function processFilelist(){ | ||
var files = w.pluck(fileList, function(val){ return val === 1; }), | ||
dirs = w.pluck(fileList, function(val){ return val === 2 || val instanceof Array; }); | ||
noExist.forEach(function(file){ | ||
log(red("File does not exist: " + file)); | ||
}); | ||
doWork(files); | ||
doWork(dirs.reverse()); | ||
} | ||
if (optionSet.valid){ | ||
if (optionSet.help){ | ||
l(usage); | ||
} else if (optionSet.name) { | ||
var toSave = optionSet.where({ | ||
name: {$ne: [ "files", "dry-run", "name" ]} | ||
}).toJSON(); | ||
presets.save(optionSet.name, toSave); | ||
} else if (optionSet.list){ | ||
l(w.ansi("Preset list", "bold", "underline")); | ||
presets.list(function(list){ | ||
Object.keys(list).forEach(function(name){ | ||
var preset = list[name]; | ||
l(w.bold(name), preset.description, "[" + preset.user + "]"); | ||
if (optionSet.verbose){ | ||
delete preset.description; | ||
delete preset.user; | ||
Object.keys(preset).forEach(function(option){ | ||
l(option + ":", preset[option]); | ||
}); | ||
} | ||
}); | ||
}); | ||
} else if (optionSet.preset){ | ||
presets.load(optionSet.preset, function(preset){ | ||
optionSet.set(preset); | ||
processFilelist(); | ||
}); | ||
} else if (optionSet.files.length){ | ||
processFilelist(); | ||
} else { | ||
l(usage); | ||
} | ||
} else { | ||
log(red("Some values were invalid")); | ||
log(red(optionSet.validationMessages.toString())); | ||
log(usage); | ||
logError("Some values were invalid"); | ||
logError(optionSet.validationMessages.toString()); | ||
l(usage); | ||
} | ||
/* | ||
TODO: presets, replace token: $dirname, --js expression and $js token, date and string padding functions, -i option for case-insensitive | ||
TODO: replace token: $dirname, --js expression and $js token, date and string padding functions | ||
renamer -i -f "something" -r "$1" --findModifier 'toUpperCase()' // returns SOMETHING | ||
renamer -i -f "two words" -r "$1" --findModifier 'toTitleCase()' // returns Two Words | ||
*/ |
@@ -5,12 +5,20 @@ "use strict"; | ||
util = require("util"), | ||
l = console.log; | ||
wodge = require("wodge"); | ||
function escapeRegExp(string){ | ||
return string | ||
? string.replace(/([.*+?^=!:${}()|\[\]\/\\])/g, "\\$1") | ||
: ""; | ||
} | ||
var RenameOptions = exports.RenameOptions = function(){ | ||
this.define({ | ||
name: "files", | ||
type: Array, | ||
defaultOption: true, | ||
value: [] | ||
}) | ||
.define({ name: "find", type: "string", alias: "f" }) | ||
.define({ name: "replace", type: "string", alias: "r", value: "" }) | ||
.define({ name: "regex", type: "boolean", alias: "e" }) | ||
.define({ name: "insensitive", type: "boolean", alias: "i" }); | ||
}; | ||
util.inherits(RenameOptions, Thing); | ||
exports.rename = function(options){ | ||
options = new exports.RenameOptions().set(options); | ||
options = new RenameOptions().set(options); | ||
@@ -23,3 +31,3 @@ if (options.valid){ | ||
basename = path.basename(file), | ||
re = options.regex ? options.find : escapeRegExp(options.find), | ||
re = options.regex ? options.find : wodge.escapeRegExp(options.find), | ||
reOptions = "g" + (options.insensitive ? "i" : ""); | ||
@@ -46,15 +54,1 @@ | ||
}; | ||
exports.RenameOptions = function(){ | ||
this.define({ | ||
name: "files", | ||
type: Array, | ||
required: true, | ||
defaultOption: true | ||
}) | ||
.define({ name: "find", type: "string", alias: "f" }) | ||
.define({ name: "replace", type: "string", alias: "r", default: "" }) | ||
.define({ name: "regex", type: "boolean", alias: "e" }) | ||
.define({ name: "insensitive", type: "boolean", alias: "i" }); | ||
}; | ||
util.inherits(exports.RenameOptions, Thing); |
{ | ||
"name": "renamer", | ||
"description": "Batch rename files and folders", | ||
"version": "0.2.8", | ||
"version": "0.2.9", | ||
"bin": "cli.js", | ||
@@ -12,4 +12,5 @@ "repository": "https://github.com/75lb/renamer", | ||
"dependencies": { | ||
"nature": "~0.2.0", | ||
"glob": "~3.2.6" | ||
"nature": "~0.3.0", | ||
"glob": "~3.2.6", | ||
"wodge": "~0.1.0" | ||
}, | ||
@@ -16,0 +17,0 @@ "devDependencies": { |
@@ -21,16 +21,22 @@ [![NPM version](https://badge.fury.io/js/renamer.png)](http://badge.fury.io/js/renamer) | ||
```sh | ||
$ renamer [--regex] [--find <pattern>] [--replace <string>] [--dry-run] <files> | ||
$ renamer [--regex] [--find <pattern>] [--replace <string>] [--dry-run] [--verbose] [--name <string>] <files> | ||
$ renamer --list [--verbose] | ||
$ renamer --preset <files> | ||
``` | ||
``` | ||
-f, --find The find string, or regular expression when --regex is set. | ||
-f, --find The find string, or regular expression when --regex is set. | ||
If not set, the whole filename will be replaced. | ||
-r, --replace The replace string. With --regex set, --replace can reference | ||
parenthesised substrings from --find with $1, $2, $3 etc. | ||
If omitted, defaults to a blank string. The special token | ||
'{{index}}' will insert an incrementing number per file | ||
parenthesised substrings from --find with $1, $2, $3 etc. | ||
If omitted, defaults to a blank string. The special token | ||
'{{index}}' will insert an incrementing number per file | ||
processed. | ||
-e, --regex When set, --find is intepreted as a regular expression. | ||
-e, --regex When set, --find is intepreted as a regular expression. | ||
-i, --insensitive Enable case-insensitive finds. | ||
-d, --dry-run Used for test runs. Set this to do everything but rename the file. | ||
-h, --help Print usage instructions. | ||
-v, --verbose Use to print additional information. | ||
-l, --list List the available presets. | ||
-p, --preset Use the specified preset. | ||
-n, --name Save the command as a preset with the specified name. | ||
-h, --help Print usage instructions. | ||
``` | ||
@@ -211,2 +217,2 @@ | ||
[![NPM](https://nodei.co/npm-dl/renamer.png?months=3)](https://nodei.co/npm/renamer/) | ||
![NPM](https://nodei.co/npm-dl/renamer.png?months=3) |
@@ -8,6 +8,2 @@ #!/usr/bin/env node | ||
if (!fs.existsSync("fixture")){ | ||
fs.mkdir("fixture"); | ||
} | ||
function clearDir(dirName){ | ||
@@ -22,5 +18,12 @@ console.log("clearing dir: " + dirName); | ||
}); | ||
fs.rmdirSync(dirName); | ||
} | ||
clearDir("fixture"); | ||
if (fs.existsSync("fixture")){ | ||
clearDir("fixture"); | ||
} | ||
fs.mkdirSync("fixture"); | ||
fs.mkdirSync("fixture/folder"); | ||
[1,2,3,4,5].forEach(function(number){ | ||
@@ -30,2 +33,6 @@ var fileName = path.join("fixture", "file" + number + ".test"); | ||
}); | ||
[1,2,3,4,5].forEach(function(number){ | ||
var fileName = path.join("fixture/folder", "file" + number + ".test"); | ||
fs.writeFileSync(fileName, dummyContent); | ||
}); | ||
@@ -39,1 +46,13 @@ fs.writeFileSync("fixture/[#f1ipping4nn0y1ing].file.NAME--23[$1$$!].mkv", dummyContent); | ||
fs.writeFileSync("fixture/loads.of.full.stops.every.where.mp4", dummyContent); | ||
fs.writeFileSync("fixture/youtube-dl-h5yIJXdItgo.mp4", dummyContent); | ||
fs.writeFileSync("fixture/blah don't blah -Mr Blah-tkxWmh-tFGs.avi", dummyContent); | ||
fs.writeFileSync("fixture/folder/[#f1ipping4nn0y1ing].file.NAME--23[$1$$!].mkv", dummyContent); | ||
fs.writeFileSync("fixture/folder/[#f1ipping4nn0y1ing].file.NAME--3[$2$$!].mkv", dummyContent); | ||
fs.writeFileSync("fixture/folder/[#f1ipping4nn0y1ing].file.NAME--13[$3$$!].mkv", dummyContent); | ||
fs.writeFileSync("fixture/folder/[ag]_Annoying_filename_-_3_[38881CD1].mp4", dummyContent); | ||
fs.writeFileSync("fixture/folder/[eg]_Annoying_filename_-_13_[38881CD2].mp4", dummyContent); | ||
fs.writeFileSync("fixture/folder/[fg]_Annoying_filename_-_23_[38881CD3].mp4", dummyContent); | ||
fs.writeFileSync("fixture/folder/loads.of.full.stops.every.where.mp4", dummyContent); | ||
fs.writeFileSync("fixture/folder/youtube-dl-h5yIJXdItgo.mp4", dummyContent); | ||
fs.writeFileSync("fixture/folder/blah don't blah - Mr Blah-tkxWmh-tFGs.avi", dummyContent); |
var rename = require("../lib/rename"), | ||
path = require("path"), | ||
assert = require("assert"); | ||
@@ -47,5 +48,14 @@ | ||
assert.deepEqual(rename.rename(args), [ | ||
{ before: "clive/clive.txt", after: "clive/hater.txt" }, | ||
{ before: "clive/clive/clive.txt", after: "clive/clive/hater.txt" }, | ||
{ before: "clive/clive/clive/clive.txt", after: "clive/clive/clive/hater.txt" } | ||
{ | ||
before: path.join("clive", "clive.txt"), | ||
after: path.join("clive", "hater.txt") | ||
}, | ||
{ | ||
before: path.join("clive", "clive", "clive.txt"), | ||
after: path.join("clive", "clive", "hater.txt") | ||
}, | ||
{ | ||
before: path.join("clive", "clive", "clive", "clive.txt"), | ||
after: path.join("clive", "clive", "clive", "hater.txt") | ||
} | ||
]); | ||
@@ -56,9 +66,20 @@ }); | ||
var args = [ | ||
"--find", "clive", "--replace", "hater", "-i", | ||
"file CLIVe 1.txt", "&*123file clIVe 2.txt", "clicclicClivEhater.avi" | ||
"--find", "CLIve", "--replace", "hater", "-i", | ||
"clive/clive.txt", | ||
"clive/clive/clive.txt", | ||
"clive/clive/clive/clive.txt" | ||
]; | ||
assert.deepEqual(rename.rename(args), [ | ||
{ before: "file CLIVe 1.txt", after: "file hater 1.txt" }, | ||
{ before: "&*123file clIVe 2.txt", after: "&*123file hater 2.txt" }, | ||
{ before: "clicclicClivEhater.avi", after: "clicclichaterhater.avi" } | ||
{ | ||
before: path.join("clive", "clive.txt"), | ||
after: path.join("clive", "hater.txt") | ||
}, | ||
{ | ||
before: path.join("clive", "clive", "clive.txt"), | ||
after: path.join("clive", "clive", "hater.txt") | ||
}, | ||
{ | ||
before: path.join("clive", "clive", "clive", "clive.txt"), | ||
after: path.join("clive", "clive", "clive", "hater.txt") | ||
} | ||
]); | ||
@@ -91,4 +112,10 @@ }); | ||
assert.deepEqual(rename.rename(args), [ | ||
{ before: "clive/&*123file clive 2.txt", after: "clive/&*123file hater 2.txt" }, | ||
{ before: "clive/hater/clicclicclivehater.avi", after: "clive/hater/clicclichaterhater.avi" } | ||
{ | ||
before: path.join("clive", "&*123file clive 2.txt"), | ||
after: path.join("clive", "&*123file hater 2.txt") | ||
}, | ||
{ | ||
before: path.join("clive", "hater", "clicclicclivehater.avi"), | ||
after: path.join("clive", "hater", "clicclichaterhater.avi") | ||
} | ||
]); | ||
@@ -106,4 +133,4 @@ }); | ||
{ before: "rraarr", after: "rrbbrr" }, | ||
{ before: "aaa/aaaaa", after: "aaa/bbbbb" }, | ||
{ before: "aaa/rraarr", after: "aaa/rrbbrr" } | ||
{ before: path.join("aaa", "aaaaa"), after: path.join("aaa", "bbbbb") }, | ||
{ before: path.join("aaa", "rraarr"), after: path.join("aaa", "rrbbrr") } | ||
]); | ||
@@ -110,0 +137,0 @@ }); |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Network access
Supply chain riskThis module accesses the network.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
25080
10
498
217
3
4
1
+ Addedwodge@~0.1.0
+ Addednature@0.3.2(transitive)
+ Addedunderscore@1.6.0(transitive)
+ Addedwodge@0.1.50.3.2(transitive)
- Removednature@0.2.5(transitive)
- Removedunderscore@1.5.2(transitive)
Updatednature@~0.3.0