Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

renamer

Package Overview
Dependencies
Maintainers
1
Versions
63
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

renamer - npm Package Compare versions

Comparing version 0.3.1 to 0.4.0

bin/cli.js

203

lib/renamer.js
"use strict";
var Model = require("nature").Model,
/** @module renamer */
var mfs = require("more-fs"),
w = require("wodge"),
dope = require("console-dope"),
path = require("path"),

@@ -7,122 +10,84 @@ util = require("util"),

Result = require("./Result"),
mfs = require("more-fs"),
Glob = require("glob").Glob,
w = require("wodge");
RenamerOptions = require("./RenamerOptions");
exports.RenameOptions = RenameOptions;
exports.Renamer = Renamer;
exports.Result = Result;
exports.RenamerOptions = RenamerOptions;
exports.replace = replace;
exports.expand = expand;
exports.rename = rename;
exports.dryRun = dryRun;
exports.replaceIndexToken = replaceIndexToken;
function RenameOptions(){
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: "dry-run", type: "boolean", alias: "d" })
.define({ name: "insensitive", type: "boolean", alias: "i" });
}
util.inherits(RenameOptions, Model);
/**
@constructor
*/
function Renamer(options){
this._options = new RenameOptions().set(options);
if (!this._options.valid) throw new Error("Invalid options: " + this._options.validationMessages);
}
Perform the replace. If no `options.find` is supplied, the entire basename is replaced by `options.replace`.
/**
@method process
@return {Array} results An array of result objects
@example
[
{ before: "file1.txt", after: "clive.txt", renamed: false, error: "file exists" }
{ before: "file2.txt", after: "clive2.txt", renamed: true }
]
@alias module:renamer.replace
@param {RenamerOptions} options - Contains the file list and renaming options
@returns {Array} An array of ResultObject instances containing `before` and `after` info
*/
Renamer.prototype.process = function(){
var options = this._options,
fileStats = new mfs.FileStats(options.files);
function replace(options){
options = new RenamerOptions(options);
var findRegex = regExBuilder(options);
return options.files.map(function(file){
var result = new Result(),
dirname = path.dirname(file),
basename = path.basename(file);
options.files = fileStats.files
.concat(fileStats.dirs.reverse())
.map(function(file){ return { before: file }; });
if(options.find){
if (basename.search(findRegex) > -1){
basename = basename.replace(findRegex, options.replace);
result.after = path.join(dirname, basename);
} else {
/* leave result.after blank, signifying no replace was performed */
}
} else {
result.after = path.join(dirname, options.replace);
}
var results = options.files
.map(this._renameFile.bind(this))
.map(replaceIndexToken)
.map(this._dryRun.bind(this))
.map(this._renameOnDisk.bind(this));
result.before = path.normalize(file);
return result;
});
}
return results;
};
/**
Search globally by default. If `options.regex` is not set then ensure any special regex characters in `options.find` are escaped.
*/
function regExBuilder(options){
var re = options.regex ? options.find : w.escapeRegExp(options.find),
reOptions = "g" + (options.insensitive ? "i" : "");
return new RegExp(re, reOptions);
function expand(files){
var fileStats = new mfs.FileStats(files);
fileStats.filesAndDirs = fileStats.files.concat(fileStats.dirs.reverse());
return fileStats;
}
/**
Perform the replace, on the basename only. If no `options.find` is supplied, the entire basename is replaced by `options.replace`.
@method
@param result {ResultObject} input
@returns {ResultObject} resultObject An object containing the input path before and after the rename.
*/
Renamer.prototype._renameFile = function(result, index, resultsSoFar){
var after,
options = this._options,
dirname = path.dirname(result.before),
basename = path.basename(result.before),
re = regExBuilder(options);
function dryRun(resultArray){
return resultArray.map(function(result, index, resultsSoFar){
var existing = resultsSoFar.filter(function(prevResult, prevIndex){
return prevIndex < index && (prevResult.before !== result.before) && (prevResult.after === result.after);
});
if(options.find){
basename = basename.replace(re, options.replace);
after = path.join(dirname, basename);
} else {
after = path.join(dirname, options.replace);
}
if (result.before === result.after || !result.after){
result.renamed = false;
result.error = "no change";
} else if (existing.length){
result.renamed = false;
result.error = "file exists";
} else {
result.renamed = true;
}
result.before = path.normalize(result.before);
result.after = after;
result.renamed = true;
return result;
};
Renamer.prototype._dryRun = function(result, index, resultsSoFar){
var existing = resultsSoFar.filter(function(prevResult, prevIndex){
return prevIndex < index && (prevResult.before !== result.before) && (prevResult.after === result.after);
return result;
});
}
if (result.before === result.after ){
result.renamed = false;
} else if (existing.length || fs.existsSync(result.after)){
result.renamed = false;
result.error = "file exists";
}
return result;
};
/**
Perform the replace, on disk. Sets the `renamed` and/or `error` properties on the resultObject.
@method
@param result {ResultObject} input
@returns {ResultObject} resultObject
*/
Renamer.prototype._renameOnDisk = function(result){
var options = this._options;
if (!options["dry-run"] && result.renamed === true) {
function rename(resultArray){
return resultArray.map(function(result){
if (!result.after){
result.renamed = false;
result.error = "no change";
return result;
}
try {
fs.renameSync(result.before, result.after);
if (fs.existsSync(result.after)){
result.renamed = false;
result.error = "file exists";
} else {
fs.renameSync(result.before, result.after);
result.renamed = true;
}
} catch(e){

@@ -132,12 +97,22 @@ result.renamed = false;

}
}
return result;
});
}
return result;
};
function replaceIndexToken(resultArray){
return resultArray.map(function(result, index){
if (result.after){
result.after = result.after.replace("{{index}}", index + 1);
}
return result;
});
}
function replaceIndexToken(result, index){
if (result.after){
result.after = result.after.replace("{{index}}", index + 1);
}
return result;
/**
Search globally by default. If `options.regex` is not set then ensure any special regex characters in `options.find` are escaped.
*/
function regExBuilder(options){
var re = options.regex ? options.find : w.escapeRegExp(options.find),
reOptions = "g" + (options.insensitive ? "i" : "");
return new RegExp(re, reOptions);
}
module.exports = Result;
function Result(){
this.before = null;
this.after = null;
this.renamed = null;
this.error = null;
// this.before = null;
// this.after = null;
// this.renamed = null;
// this.error = null;
}
{
"name": "renamer",
"description": "Batch rename files and folders",
"version": "0.3.1",
"bin": "cli.js",
"version": "0.4.0",
"bin": "bin/cli.js",
"main": "./lib/renamer",

@@ -10,3 +10,3 @@ "repository": "https://github.com/75lb/renamer",

"scripts": {
"testx": "mocha --reporter spec test/unit-*.js"
"test": "tape test/*.js"
},

@@ -18,5 +18,7 @@ "dependencies": {

"console-dope": "~0.3",
"more-fs": "~0.1.2"
"more-fs": "~0.2"
},
"devDependencies": {}
"devDependencies": {
"tape": "~2.12.0"
}
}

@@ -38,136 +38,198 @@ [![NPM version](https://badge.fury.io/js/renamer.png)](http://badge.fury.io/js/renamer)

For more information on Regular Expressions, see [this useful guide](https://developer.mozilla.org/en/docs/Web/JavaScript/Guide/Regular_Expressions).
For more information on Regular Expressions, see [this useful guide](https://developer.mozilla.org/en/docs/Web/JavaScript/Guide/Regular_Expressions).
**Don't forget to test your rename first using `--dry-run`!**
Globbing
--------
Renamer comes with globbing support built in (provided by [node-glob](https://github.com/isaacs/node-glob)). If you want to override your shell's native [expansion](http://www.gnu.org/software/bash/manual/bashref.html#Shell-Expansions) behaviour (say, for example it lacks the [globstar](http://www.linuxjournal.com/content/globstar-new-bash-globbing-option) option), pass the glob expression in single quotes and renamer will expand it. For example, this command operates on all js files, recursively:
Recursing
---------
Renamer comes with globbing support built in (provided by [node-glob](https://github.com/isaacs/node-glob)), enabling recursive operations. To recurse, use the `**` wildcard where a directory name would appear to apply the meaning "any directory, including this one".
$ renamer -f 'this' -r 'that' '**/*.js'
For example, this command operates on all js files in the current directory:
$ renamer --find this --replace that *.js
this command operates on all js files, recursively:
$ renamer --find this --replace that **/*.js
this command operates on all js files from the `lib` directory downward:
$ renamer --find this --replace that lib/**/*.js
**Bash users without globstar will need to enclose the glob expression in quotes to prevent native file expansion**, i.e. `"**/*.js"`
Examples
--------
_Simple replace_
###Simple replace
```sh
$ tree -N
.
├── A poem [bad].txt
├── A story [bad].txt
$ renamer --find '[bad]' --replace '[good]' *
```
$ tree -N
.
<table>
<thead>
<tr><th>Before</th><th>After</th></tr>
</thead>
<tbody>
<tr>
<td><pre><code>.
├── A poem [bad].txt
├── A story [bad].txt</code></pre></td>
<td><pre><code>.
├── A poem [good].txt
├── A story [good].txt
```
├── A story [good].txt</code></pre></td>
</tr>
</tbody>
</table>
_Case insenstive finds_
###Case insenstive finds
```sh
$ tree -N
.
$ renamer --insensitive --find 'mpeg4' --replace 'mp4' *
```
<table>
<thead>
<tr><th>Before</th><th>After</th></tr>
</thead>
<tbody>
<tr>
<td><pre><code>.
├── A video.MPEG4
├── Another video.Mpeg4
$ renamer --insensitive --find 'mpeg4' --replace 'mp4' *
$ tree -N
.
├── Another video.Mpeg4</code></pre></td>
<td><pre><code>.
├── A video.mp4
├── Another video.mp4
```
├── Another video.mp4</code></pre></td>
</tr>
</tbody>
</table>
_Strip out unwanted text_:
###Strip out unwanted text
```sh
$ tree -N
.
├── Season 1 - Some crappy episode.mp4
├── Season 1 - Load of bollocks.mp4
$ renamer --find 'Season 1 - ' *
```
$ tree -N
.
<table>
<thead>
<tr><th>Before</th><th>After</th></tr>
</thead>
<tbody>
<tr>
<td><pre><code>.
├── Season 1 - Some crappy episode.mp4
├── Season 1 - Load of bollocks.mp4</code></pre></td>
<td><pre><code>.
├── Some crappy episode.mp4
├── Load of bollocks.mp4
```
├── Load of bollocks.mp4</code></pre></td>
</tr>
</tbody>
</table>
_Simple filename cleanup_:
###Simple filename cleanup
```sh
$ tree
.
$ renamer --regex --find '.*_(\d+)_.*' --replace 'Video $1.mp4' *
```
<table>
<thead>
<tr><th>Before</th><th>After</th></tr>
</thead>
<tbody>
<tr>
<td><pre><code>.
├── [ag]_Annoying_filename_-_3_[38881CD1].mp4
├── [ag]_Annoying_filename_-_34_[38881CD1].mp4
├── [ag]_Annoying_filename_-_53_[38881CD1].mp4
$ renamer --regex --find '.*_(\d+)_.*' --replace 'Video $1.mp4' *
$ tree
.
├── [ag]_Annoying_filename_-_53_[38881CD1].mp4</code></pre></td>
<td><pre><code>.
├── Video 3.mp4
├── Video 34.mp4
├── Video 53.mp4
```
├── Video 53.mp4</code></pre></td>
</tr>
</tbody>
</table>
_Give your images a new numbering scheme_:
###Give your images a new numbering scheme
```sh
$ tree
.
$ renamer --replace 'Image{{index}}.jpg' *
```
<table>
<thead>
<tr><th>Before</th><th>After</th></tr>
</thead>
<tbody>
<tr>
<td><pre><code>.
├── IMG_5776.JPG
├── IMG_5777.JPG
├── IMG_5778.JPG
$ renamer --replace 'Image{{index}}.jpg' *
$ tree
.
├── IMG_5778.JPG</code></pre></td>
<td><pre><code>.
├── Image1.jpg
├── Image2.jpg
├── Image3.jpg
```
├── Image3.jpg</code></pre></td>
</tr>
</tbody>
</table>
_do something about all those full stops_:
###do something about all those full stops
```sh
$ tree
.
├── loads.of.full.stops.every.where.jpeg
├── loads.of.full.stops.every.where.mp4
$ renamer --regex --find '\.(?!\w+$)' --replace ' ' *
```
$ tree
.
<table>
<thead>
<tr><th>Before</th><th>After</th></tr>
</thead>
<tbody>
<tr>
<td><pre><code>.
├── loads.of.full.stops.every.where.jpeg
├── loads.of.full.stops.every.where.mp4</code></pre></td>
<td><pre><code>.
├── loads of full stops every where.jpeg
├── loads of full stops every where.mp4
├── loads of full stops every where.mp4</code></pre></td>
</tr>
</tbody>
</table>
###if not already done, add your name to a load of files
```sh
$ renamer --regex --find '(data\d)(\.\w+)' --replace '$1 (checked by Lloyd)$2' *
```
_if not already done, add your name to a load of files_:
```sh
$ tree
.
<table>
<thead>
<tr><th>Before</th><th>After</th></tr>
</thead>
<tbody>
<tr>
<td><pre><code>.
├── data1.csv
├── data2 (checked by Lloyd).csv
├── data3.xls
├── data3.xls</code></pre></td>
<td><pre><code>.
├── data1 (checked by Lloyd).csv
├── data2 (checked by Lloyd).csv
├── data3 (checked by Lloyd).xls</code></pre></td>
</tr>
</tbody>
</table>
$ renamer --regex --find '(data\d)(\.\w+)' --replace '$1 (checked by Lloyd)$2' *
$ tree
.
├── data1 (checked by Lloyd).csv
├── data2 (checked by Lloyd).csv
├── data3 (checked by Lloyd).xls
###rename files and folders, recursively
```sh
$ renamer --find 'pic' --replace 'photo' '**'
```
_rename files and folders, recursively_
```sh
$ tree
.
<table>
<thead>
<tr><th>Before</th><th>After</th></tr>
</thead>
<tbody>
<tr>
<td><pre><code>.
├── pic1.jpg

@@ -178,7 +240,4 @@ ├── pic2.jpg

└── pic4.jpg
$ renamer --find 'pic' --replace 'photo' '**'
$ tree
.
</code></pre></td>
<td><pre><code>.
├── photo1.jpg

@@ -188,10 +247,20 @@ ├── photo2.jpg

├── photo3.jpg
└── photo4.jpg
```
└── photo4.jpg</code></pre></td>
</tr>
</tbody>
</table>
_prefix files and folders, recursively_
###prefix files and folders, recursively
```sh
$ tree
.
$ renamer --regex --find '^' --replace 'good-' '**'
```
<table>
<thead>
<tr><th>Before</th><th>After</th></tr>
</thead>
<tbody>
<tr>
<td><pre><code>.
├── pic1.jpg

@@ -202,7 +271,4 @@ ├── pic2.jpg

└── pic4.jpg
$ renamer --regex --find '^' --replace 'good-' '**'
$ tree
.
</code></pre></td>
<td><pre><code>.
├── good-pic1.jpg

@@ -212,5 +278,7 @@ ├── good-pic2.jpg

├── good-pic3.jpg
└── good-pic4.jpg
```
└── good-pic4.jpg</code></pre></td>
</tr>
</tbody>
</table>
![NPM](https://nodei.co/npm-dl/renamer.png?months=3)

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc