New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.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.7.0 to 1.0.0-0

lib/cli-app.js

75

bin/cli.js
#!/usr/bin/env node
'use strict'
const commandLineArgs = require('command-line-args')
const commandLineUsage = require('command-line-usage')
const cliOptions = require('../lib/cliOptions')
const renamer = require('../')
const ansi = require('ansi-escape-sequences')
const usageSections = [
{
header: 'renamer',
content: 'Batch rename files and folders.'
},
{
header: 'Synopsis',
content: '$ renamer <options> <files>'
},
{
header: 'Options',
optionList: cliOptions,
hide: 'files'
},
{
content: 'for more detailed instructions, visit {underline https://github.com/75lb/renamer}'
}
]
let options
try {
options = commandLineArgs(cliOptions)
} catch (err) {
halt(err)
}
if (options.help) {
console.log(commandLineUsage(usageSections))
} else if (options.files.length) {
const fileStats = renamer.expand(options.files)
options.files = fileStats.filesAndDirs
fileStats.notExisting.forEach(function (file) {
log(options.verbose, { before: file, error: 'does not exist' })
})
let results = renamer.replace(options)
results = renamer.replaceIndexToken(results)
if (results.list.length) {
if (options['dry-run']) {
console.log(ansi.format('Dry run', ['bold', 'underline']))
renamer.dryRun(results).list.forEach(log.bind(null, options.verbose))
} else {
renamer.rename(results).list.forEach(log.bind(null, options.verbose))
}
}
} else {
console.error(ansi.format('No input files supplied', 'red'))
console.log(commandLineUsage(usageSections))
}
function log (verbose, result) {
if (!verbose && !result.renamed) return
const tick = process.platform === 'win32' ? '√' : '✔︎'
const cross = process.platform === 'win32' ? '×': '✖'
const symbol = `{${result.renamed ? 'green' : 'red'} ${result.renamed ? tick : cross}}`
const desc = result.before + (result.after ? ' -> ' + result.after : '')
const errDesc = result.error ? `({red ${result.error}})` : ''
console.log(ansi.format(`${symbol} ${desc} ${errDesc}`))
}
function halt (err) {
console.error(ansi.format(err.stack, 'red'))
process.exit(1)
}
const CliApp = require('../lib/cli-app')
const cliApp = new CliApp()
module.exports = cliApp.start()

@@ -1,9 +0,2 @@

'use strict'
const fileSet = require('file-set')
const path = require('path')
const fs = require('fs')
const Result = require('./lib/Result')
const Results = require('./lib/Results')
const os = require('os')
const t = require('typical')
const EventEmitter = require('events').EventEmitter

@@ -13,129 +6,44 @@ /**

*/
exports.Result = Result
exports.Results = Results
exports.replace = replace
exports.expand = expand
exports.rename = rename
exports.dryRun = dryRun
exports.replaceIndexToken = replaceIndexToken
/**
* Perform the replace. If no `options.find` is supplied, the entire basename is replaced by `options.replace`.
*
* @param {Object} options - Contains the file list and renaming options
* @returns {Array} An array of ResultObject instances containing `before` and `after` info
* @alias module:renamer
*/
function replace (options) {
if (!t.isPlainObject(options)) throw new Error('Invalid options supplied')
const findRegex = regExBuilder(options)
const results = new Results()
results.list = options.files.map(replaceSingle.bind(null, findRegex, options.replace))
return results
}
class Renamer extends EventEmitter {
/**
* @param {object} options - The renamer options
* @param {string[]} [options.files] - One or more glob patterns or names of files to rename.
* @param {sting|RegExp} [options.find] - Find expression.
* @param {string} [options.replace]
* @param {boolean} [options.dryRun]
* @param {boolean} [options.force]
* @param {string[]} [options.plugin]
* @emits module:renamer#rename-start
*/
rename (options) {
const renameFile = require('./lib/rename-file')
const Replacer = require('./lib/replacer')
const util = require('./lib/util')
function replaceSingle (findRegex, replace, file) {
const result = new Result({ before: path.normalize(file) })
const dirname = path.dirname(file)
let basename = path.basename(file)
if (findRegex) {
if (basename.search(findRegex) > -1) {
basename = basename.replace(findRegex, replace)
result.after = path.join(dirname, basename)
} else {
/* leave result.after blank, signifying no replace was performed */
}
} else {
result.after = path.join(dirname, replace)
}
return result
}
function expand (files) {
const fileStats = fileSet(files)
fileStats.filesAndDirs = fileStats.files.concat(fileStats.dirs.reverse())
return fileStats
}
/**
Takes a Results collection in, sets `renamed` and/or `error` on each with the expected values
@param {Results} results - the Results collection to operate on
@returns {Results} results
*/
function dryRun (results) {
results.list = results.list.map(function (result, index, resultsSoFar) {
const existing = resultsSoFar.filter(function (prevResult, prevIndex) {
return prevIndex < index && (prevResult.before !== result.before) && (prevResult.after === result.after)
})
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
}
return result
})
return results
}
/**
Takes a Results collection in, performs the rename on disk setting `renamer` and `error` as appropriate
@param {Results} results - the Results collection to operate on
@returns {Results} results
*/
function rename (results) {
results.list = results.list.map(function (result) {
if (!result.after) {
result.renamed = false
result.error = 'no change'
return result
}
try {
if (fs.existsSync(result.after)) {
result.renamed = false
result.error = 'file exists'
} else {
fs.renameSync(result.before, result.after)
result.renamed = true
const files = util.expandGlobPatterns(options.files)
const replacer = new Replacer(options.plugin)
const replaceResults = files
.map((file, index) => replacer.replace(file, options.find, options.replace, options.plugin, index, files))
.sort((a, b) => util.depthFirstCompare(a.from, b.from))
for (const replaceResult of replaceResults) {
/**
* Rename start
* @event module:renamer#rename-start
* @type {object}
* @property {string} from
* @property {string} to
*/
this.emit('rename-start', replaceResult)
if (replaceResult.renamed) {
renameFile(replaceResult.from, replaceResult.to, { force: options.force, dryRun: options.dryRun })
this.emit('rename-end', replaceResult)
}
} catch (e) {
result.renamed = false
result.error = e.message
}
return result
})
return results
}
function replaceIndexToken (results) {
results.list = results.list.map(function (result, index) {
if (result.after) {
result.after = result.after.replace(/{{index}}/g, index + 1)
}
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. Do nothing if `options.find` is not set.
*/
function regExBuilder (options) {
if (options.find) {
const re = options.regex ? options.find : escapeRegExp(options.find)
const reOptions = 'g' + (options.insensitive ? 'i' : '')
return new RegExp(re, reOptions)
}
}
function escapeRegExp(string){
return string
? string.replace(/([.*+?^=!:${}()|\[\]\/\\])/g, '\\$1')
: ''
}
module.exports = Renamer
{
"name": "renamer",
"description": "Batch rename files and folders",
"version": "0.7.0",
"description": "Rename files in bulk",
"version": "1.0.0-0",
"author": "Lloyd Brookes <75pound@gmail.com>",

@@ -9,5 +9,10 @@ "bin": "bin/cli.js",

"engines": {
"node": ">=4.0.0"
"node": ">=8.0.0"
},
"repository": "https://github.com/75lb/renamer",
"files": [
"index.js",
"lib",
"bin"
],
"keywords": [

@@ -23,17 +28,21 @@ "rename",

"scripts": {
"test": "test-runner test/cli.js test/renamer.*.js"
"test": "test-runner test/*.js",
"docs": "jsdoc2md index.js > docs/API.md",
"cover": "nyc --reporter=text-lcov test-runner test/*.js | coveralls"
},
"dependencies": {
"ansi-escape-sequences": "^4.0.0",
"array-back": "^2.0.0",
"chalk": "^2.4.1",
"command-line-args": "^5.0.2",
"command-line-usage": "^5.0.5",
"file-set": "^2.0.0",
"test-value": "^3.0.0",
"typical": "^2.6.1"
"glob": "^7.1.2",
"reduce-flatten": "^2.0.0",
"reduce-unique": "^2.0.1",
"stream-read-all": "^1.0.1"
},
"devDependencies": {
"more-fs": "~0.5.0",
"coveralls": "^3.0.1",
"mkdirp2": "^1.0.4",
"rimraf": "^2.6.2",
"test-runner": "^0.5.0"
}
}
[![view on npm](http://img.shields.io/npm/v/renamer.svg)](https://www.npmjs.org/package/renamer)
[![npm module downloads](http://img.shields.io/npm/dt/renamer.svg)](https://www.npmjs.org/package/renamer)
[![Build Status](https://travis-ci.org/75lb/renamer.svg?branch=master)](https://travis-ci.org/75lb/renamer)
[![Coverage Status](https://coveralls.io/repos/github/75lb/renamer/badge.svg?branch=next)](https://coveralls.io/github/75lb/renamer?branch=next)
[![Dependency Status](https://david-dm.org/75lb/renamer.svg)](https://david-dm.org/75lb/renamer)
[![js-standard-style](https://img.shields.io/badge/code%20style-standard-brightgreen.svg)](https://github.com/feross/standard)
renamer
=======
Batch rename files and folders.
***renamer v1.0.0 and this documentation is a WIP***
Install
-------
Install [node](https://nodejs.org) then:
```sh
$ npm install -g renamer
```
*Linux/Mac users may need to run the above with `sudo`*
# renamer
Renamer is a command-line utility intended to help rename files and folders in bulk. It is flexible and extensible via plugins.
Usage
-----
```
renamer
Batch rename files and folders.
## Disclaimer
Usage
$ renamer <options> <files>
Always run this tool with the `--dry-run` option until you are confident the results look correct.
-f, --find <string> The find string, or regular expression when --regex is set. If not set, the whole filename will be replaced.
-r, --replace <string> 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 processed.
-e, --regex When set, --find is interpreted as a regular expression.
-d, --dry-run Used for test runs. Set this to do everything but rename the file.
-i, --insensitive Enable case-insensitive finds.
-v, --verbose Use to print additional information.
-h, --help Print usage instructions.
## Synopsis
for more detailed instructions, visit https://github.com/75lb/renamer
```
As input, renamer takes a list of filenames or glob patterns plus some options describing how you would like the files to be renamed. If no filesnames/patterns are specified, renamer will look for a newline-separated list of filenames on standard input.
For more information on Regular Expressions, see [this useful guide](https://developer.mozilla.org/en/docs/Web/JavaScript/Guide/Regular_Expressions).
<pre><code>$ renamer [options] [<u>file</u> <u>...</u>]
</pre></code>
**Don't forget to test your rename procedure first using `--dry-run`!**
Trivial example. It will replace the text `jpeg` with `jpg` in all files or folders in the current directory.
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 --find jpeg --replace jpg *
```
For example, this command operates on all `js` files in the current directory:
As above but operates on all files and folders recursively.
$ renamer --find this --replace that '*.js'
```
$ renamer --find jpeg --replace jpg "**"
```
this command operates on all `js` files, recursively:
Same operation but on a filename list supplied via stdin. This approach is useful for crafting a more specific input list using tools like `find`. This example operates on files modified less than 20 minutes ago.
$ renamer --find this --replace that '**/*.js'
```
$ find . -mtime -20m | renamer --find jpeg --replace jpg
```
this command operates on all `js` files from the `lib` directory downward:
Same again but with a hand-rolled input of filenames and glob patterns. Create an input text file, e.g. `files.txt`:
$ renamer --find this --replace that 'lib/**/*.js'
```
house.jpeg
garden.jpeg
img/*
```
**Bash users without globstar will need to enclose the glob expression in quotes to prevent native file expansion**, i.e. `'**/*.js'`
Then pipe it into renamer.
Examples
--------
Some real-world examples.
**Windows users**: the single-quotation marks used in the example commands below are for bash (Mac/Linux) users, please replace these with double-quotation marks on Windows.
### Simple replace
```sh
$ renamer --find '[bad]' --replace '[good]' *
```
$ cat files.txt | renamer --find jpeg --replace jpg
```
<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</code></pre></td>
</tr>
</tbody>
</table>
Simple example using a [regular expression literal](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions). The case-insensitive pattern `/one/i` matches the input file `ONE.jpg`, renaming it to `two.jpg`.
### Case insenstive finds
```sh
$ 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</code></pre></td>
<td><pre><code>.
├── A video.mp4
├── Another video.mp4</code></pre></td>
</tr>
</tbody>
</table>
$ renamer --find '/one/i' --replace 'two' ONE.jpg
```
### Strip out unwanted text
The full set of command-line options.
```sh
$ renamer --find 'Season 1 - ' *
```
-f, --find string Optional find string (e.g. "one") or regular expression literal (e.g.
"/one/i"). If omitted, the whole filename will be matched and replaced.
-r, --replace string The replace string. If omitted, defaults to a empty string. The special token
'{{index}}' will insert a number, incremented each time a file is replaced.
-d, --dry-run Used for test runs. Set this to do everything but rename the file.
--force If the target path already exists, overwrite it. Use with caution.
-v, --verbose In the output, also include names of files that were not renamed.
-h, --help Print usage instructions.
```
<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</code></pre></td>
</tr>
</tbody>
</table>
For more information on Regular Expressions, see [this useful guide](https://developer.mozilla.org/en/docs/Web/JavaScript/Guide/Regular_Expressions).
### Simple filename cleanup
## Globbing
```sh
$ renamer --regex --find '.*_(\d+)_.*' --replace 'Video $1.mp4' *
```
Renamer comes with globbing support built in supporting all special characters [described here](https://github.com/isaacs/node-glob#glob-primer).
<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</code></pre></td>
<td><pre><code>.
├── Video 3.mp4
├── Video 34.mp4
├── Video 53.mp4</code></pre></td>
</tr>
</tbody>
</table>
For example, this command operates on all `js` files in the current directory:
### Give your images a new numbering scheme
```sh
$ renamer --replace 'Image{{index}}.jpg' *
```
$ renamer --find this --replace that '*.js'
```
<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</code></pre></td>
<td><pre><code>.
├── Image1.jpg
├── Image2.jpg
├── Image3.jpg</code></pre></td>
</tr>
</tbody>
</table>
This command operates on all `js` files, recursively:
### do something about all those full stops
```sh
$ renamer --regex --find '\.(?!\w+$)' --replace ' ' *
```
$ renamer --find this --replace that '**/*.js'
```
<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</code></pre></td>
</tr>
</tbody>
</table>
this command operates on all `js` files from the `lib` directory downward:
### 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' *
```
$ renamer --find this --replace that 'lib/**/*.js'
```
<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</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>
**Bash users without globstar will need to enclose the glob expression in quotes to prevent native file expansion**, i.e. `'**/*.js'`
## Further reading
### rename files and folders, recursively
Please see [the wiki](https://github.com/75lb/renamer/wiki) for more documentation and examples.
```sh
$ renamer --find 'pic' --replace 'photo' '**'
```
## Install
<table>
<thead>
<tr><th>Before</th><th>After</th></tr>
</thead>
<tbody>
<tr>
<td><pre><code>.
├── pic1.jpg
├── pic2.jpg
└── pics
├── pic3.jpg
└── pic4.jpg
</code></pre></td>
<td><pre><code>.
├── photo1.jpg
├── photo2.jpg
└── photos
├── photo3.jpg
└── photo4.jpg</code></pre></td>
</tr>
</tbody>
</table>
### prefix files and folders, recursively
```sh
$ renamer --regex --find '^' --replace 'good-' '**'
```
$ npm install -g renamer@next
```
<table>
<thead>
<tr><th>Before</th><th>After</th></tr>
</thead>
<tbody>
<tr>
<td><pre><code>.
├── pic1.jpg
├── pic2.jpg
└── pics
├── pic3.jpg
└── pic4.jpg
</code></pre></td>
<td><pre><code>.
├── good-pic1.jpg
├── good-pic2.jpg
└── good-pics
├── good-pic3.jpg
└── good-pic4.jpg</code></pre></td>
</tr>
</tbody>
</table>
* * *
&copy; 2012-18 Lloyd Brookes \<75pound@gmail.com\>. Documented by [jsdoc-to-markdown](https://github.com/75lb/jsdoc-to-markdown).
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