UNPKG

14 kBMarkdownView Raw
1# Replace in file
2
3[![npm version](https://img.shields.io/npm/v/replace-in-file.svg)](https://www.npmjs.com/package/replace-in-file)
4[![build status](https://travis-ci.org/adamreisnz/replace-in-file.svg?branch=master)](https://travis-ci.org/adamreisnz/replace-in-file)
5[![coverage status](https://coveralls.io/repos/github/adamreisnz/replace-in-file/badge.svg?branch=master)](https://coveralls.io/github/adamreisnz/replace-in-file?branch=master)
6[![github issues](https://img.shields.io/github/issues/adamreisnz/replace-in-file.svg)](https://github.com/adamreisnz/replace-in-file/issues)
7
8A simple utility to quickly replace text in one or more files or globs. Works synchronously or asynchronously with either promises or callbacks. Make a single replacement or multiple replacements at once.
9
10# Index
11- [Installation](#installation)
12- [Basic usage](#basic-usage)
13 - [Asynchronous replacement with `async`/`await`](#asynchronous-replacement-with-asyncawait)
14 - [Asynchronous replacement with promises](asynchronous-replacement-with-promises)
15 - [Asynchronous replacement with callback](#asynchronous-replacement-with-callback)
16 - [Synchronous replacement](#synchronous-replacement)
17 - [Return value](#return-value)
18 - [Counting matches and replacements](#counting-matches-and-replacements)
19 - [Custom processor](#custom-processor)
20- [Advanced usage](#advanced-usage)
21 - [Replace a single file or glob](#replace-a-single-file-or-glob)
22 - [Replace multiple files or globs](#replace-multiple-files-or-globs)
23 - [Replace first occurrence only](#replace-first-occurrence-only)
24 - [Replace all occurrences](#replace-all-occurrences)
25 - [Multiple values with the same replacement](#multiple-values-with-the-same-replacement)
26 - [Custom regular expressions](#custom-regular-expressions)
27 - [Multiple values with different replacements](#multiple-values-with-different-replacements)
28 - [Using callbacks for `from`](#using-callbacks-for-from)
29 - [Using callbacks for `to`](#using-callbacks-for-to)
30 - [Ignore a single file or glob](#ignore-a-single-file-or-glob)
31 - [Ignore multiple files or globs](#ignore-multiple-files-or-globs)
32 - [Allow empty/invalid paths](#allow-emptyinvalid-paths)
33 - [Disable globs](#disable-globs)
34 - [Specify glob configuration](#specify-glob-configuration)
35 - [Making replacements on network drives](#making-replacements-on-network-drives)
36 - [Specify character encoding](#specify-character-encoding)
37 - [Dry run](#dry-run)
38- [CLI usage](#cli-usage)
39- [A note on using globs with the CLI](#a-note-on-using-globs-with-the-cli)
40- [Version information](#version-information)
41- [License](#license)
42
43## Installation
44```shell
45# Using npm, installing to local project
46npm i --save replace-in-file
47
48# Using npm, installing globally for global cli usage
49npm i -g replace-in-file
50
51# Using yarn
52yarn add replace-in-file
53```
54
55## Basic usage
56
57```js
58//Load the library and specify options
59const replace = require('replace-in-file');
60const options = {
61 files: 'path/to/file',
62 from: /foo/g,
63 to: 'bar',
64};
65```
66
67### Asynchronous replacement with `async`/`await`
68
69```js
70try {
71 const results = await replace(options)
72 console.log('Replacement results:', results);
73}
74catch (error) {
75 console.error('Error occurred:', error);
76}
77```
78
79### Asynchronous replacement with promises
80
81```js
82replace(options)
83 .then(results => {
84 console.log('Replacement results:', results);
85 })
86 .catch(error => {
87 console.error('Error occurred:', error);
88 });
89```
90
91### Asynchronous replacement with callback
92
93```js
94replace(options, (error, results) => {
95 if (error) {
96 return console.error('Error occurred:', error);
97 }
98 console.log('Replacement results:', results);
99});
100```
101
102### Synchronous replacement
103
104```js
105try {
106 const results = replace.sync(options);
107 console.log('Replacement results:', results);
108}
109catch (error) {
110 console.error('Error occurred:', error);
111}
112```
113
114### Return value
115
116The return value of the library is an array of replacement results against each file that was processed. This includes files in which no replacements were made.
117
118Each result contains the following values:
119
120- `file`: The path to the file that was processed
121- `hasChanged`: Flag to indicate if the file was changed or not
122
123```js
124const results = replace.sync({
125 files: 'path/to/files/*.html',
126 from: /foo/g,
127 to: 'bar',
128});
129
130console.log(results);
131
132// [
133// {
134// file: 'path/to/files/file1.html',
135// hasChanged: true,
136// },
137// {
138// file: 'path/to/files/file2.html',
139// hasChanged: true,
140// },
141// {
142// file: 'path/to/files/file3.html',
143// hasChanged: false,
144// },
145// ]
146
147```
148
149To get an array of changed files, simply map the results as follows:
150
151```js
152const changedFiles = results
153 .filter(result => result.hasChanged)
154 .map(result => result.file);
155```
156
157### Counting matches and replacements
158By setting the `countMatches` configuration flag to `true`, the number of matches and replacements per file will be counted and present in the results array.
159
160- `numMatches`: Indicates the number of times a match was found in the file
161- `numReplacements`: Indicates the number of times a replacement was made in the file
162
163Note that the number of matches can be higher than the number of replacements if a match and replacement are the same string.
164
165```js
166const results = replace.sync({
167 files: 'path/to/files/*.html',
168 from: /foo/g,
169 to: 'bar',
170 countMatches: true,
171});
172
173console.log(results);
174
175// [
176// {
177// file: 'path/to/files/file1.html',
178// hasChanged: true,
179// numMatches: 3,
180// numReplacements: 3,
181// },
182// {
183// file: 'path/to/files/file2.html',
184// hasChanged: true,
185// numMatches: 1,
186// numReplacements: 1,
187// },
188// {
189// file: 'path/to/files/file3.html',
190// hasChanged: false,
191// numMatches: 0,
192// numReplacements: 0,
193// },
194// ]
195```
196
197### Custom processor
198
199For advanced usage where complex processing is needed it's possible to use a callback that will receive content as an argument and should return it processed.
200
201```js
202const results = replace.sync({
203 files: 'path/to/files/*.html',
204 processor: (input) => input.replace(/foo/g, 'bar'),
205});
206```
207
208### Array of custom processors
209
210Passing processor function also supports passing an array of functions that will be executed sequentially
211
212```js
213function someProcessingA(input) {
214 const chapters = input.split('###')
215 chapters[1] = chapters[1].replace(/foo/g, 'bar')
216 return chapters.join('###')
217}
218
219function someProcessingB(input) {
220 return input.replace(/foo/g, 'bar')
221}
222
223const results = replace.sync({
224 files: 'path/to/files/*.html',
225 processor: [someProcessingA, someProcessingB],
226});
227```
228
229## Advanced usage
230
231### Replace a single file or glob
232```js
233const options = {
234 files: 'path/to/file',
235};
236```
237
238### Replace multiple files or globs
239
240```js
241const options = {
242 files: [
243 'path/to/file',
244 'path/to/other/file',
245 'path/to/files/*.html',
246 'another/**/*.path',
247 ],
248};
249```
250
251### Replace first occurrence only
252
253```js
254const options = {
255 from: 'foo',
256 to: 'bar',
257};
258```
259
260### Replace all occurrences
261Please note that the value specified in the `from` parameter is passed straight to the native [String replace method](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace). As such, if you pass a string as the `from` parameter, it will _only replace the first occurrence_.
262
263To replace multiple occurrences at once, you must use a regular expression for the `from` parameter with the global flag enabled, e.g. `/foo/g`.
264
265```js
266const options = {
267 from: /foo/g,
268 to: 'bar',
269};
270```
271
272### Multiple values with the same replacement
273
274These will be replaced sequentially.
275
276```js
277const options = {
278 from: [/foo/g, /baz/g],
279 to: 'bar',
280};
281```
282
283### Multiple values with different replacements
284
285These will be replaced sequentially.
286
287```js
288const options = {
289 from: [/foo/g, /baz/g],
290 to: ['bar', 'bax'],
291};
292```
293
294### Custom regular expressions
295
296Use the [RegExp](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp) constructor to create any regular expression.
297
298```js
299const str = 'foo';
300const regex = new RegExp('^' + str + 'bar', 'i');
301const options = {
302 from: regex,
303 to: 'bar',
304};
305```
306
307### Using callbacks for `from`
308You can also specify a callback that returns a string or a regular expression. The callback receives the name of the file in which the replacement is being performed, thereby allowing the user to tailor the search string. The following example uses a callback to produce a search string dependent on the filename:
309
310```js
311const options = {
312 files: 'path/to/file',
313 from: (file) => new RegExp(file, 'g'),
314 to: 'bar',
315};
316```
317
318### Using callbacks for `to`
319As the `to` parameter is passed to the native [String replace method](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace), you can also specify a callback. The following example uses a callback to convert matching strings to lowercase:
320
321```js
322const options = {
323 files: 'path/to/file',
324 from: /SomePattern[A-Za-z-]+/g,
325 to: (match) => match.toLowerCase(),
326};
327```
328
329This callback provides for an extra argument above the String replace method, which is the name of the file in which the replacement is being performed. The following example replaces the matched string with the filename:
330
331```js
332const options = {
333 files: 'path/to/file',
334 from: /SomePattern[A-Za-z-]+/g,
335 to: (...args) => args.pop(),
336};
337```
338
339### Ignore a single file or glob
340
341```js
342const options = {
343 ignore: 'path/to/ignored/file',
344};
345```
346
347### Ignore multiple files or globs
348
349```js
350const options = {
351 ignore: [
352 'path/to/ignored/file',
353 'path/to/other/ignored_file',
354 'path/to/ignored_files/*.html',
355 'another/**/*.ignore',
356 ],
357};
358```
359
360Please note that there is an [open issue with Glob](https://github.com/isaacs/node-glob/issues/309) that causes ignored patterns to be ignored when using a `./` prefix in your files glob. To work around this, simply remove the prefix, e.g. use `**/*` instead of `./**/*`.
361
362### Allow empty/invalid paths
363If set to true, empty or invalid paths will fail silently and no error will be thrown. For asynchronous replacement only. Defaults to `false`.
364
365```js
366const options = {
367 allowEmptyPaths: true,
368};
369```
370
371### Disable globs
372You can disable globs if needed using this flag. Use this when you run into issues with file paths like files like `//SERVER/share/file.txt`. Defaults to `false`.
373
374```js
375const options = {
376 disableGlobs: true,
377};
378```
379
380### Specify glob configuration
381Specify configuration passed to the [glob](https://www.npmjs.com/package/glob) call:
382
383```js
384const options = {
385 glob: {
386 //Glob settings here
387 dot: true, //E.g. to include file names starting with a dot
388 },
389};
390```
391
392Please note that the setting `nodir` will always be passed as `false`.
393
394### Making replacements on network drives
395To make replacements in files on network drives, you may need to specify the UNC path as the `cwd` config option. This will then be passed to glob and prefixed to your paths accordingly. See [#56](https://github.com/adamreisnz/replace-in-file/issues/56) for more details.
396
397### Specify character encoding
398Use a different character encoding for reading/writing files. Defaults to `utf-8`.
399
400```js
401const options = {
402 encoding: 'utf8',
403};
404```
405
406### Dry run
407To do a dry run without actually making replacements, for testing purposes. Defaults to `false`.
408
409```js
410const options = {
411 dry: true,
412};
413```
414
415## CLI usage
416
417```sh
418replace-in-file from to some/file.js,some/**/glob.js
419 [--configFile=replace-config.js]
420 [--ignore=ignore/files.js,ignore/**/glob.js]
421 [--encoding=utf-8]
422 [--disableGlobs]
423 [--isRegex]
424 [--verbose]
425 [--quiet]
426 [--dry]
427```
428
429Multiple files or globs can be replaced by providing a comma separated list.
430
431The flags `--disableGlobs`, `--ignore` and `--encoding` are supported in the CLI.
432
433The setting `allowEmptyPaths` is not supported in the CLI as the replacement is
434synchronous, and this setting is only relevant for asynchronous replacement.
435
436To list the changed files, use the `--verbose` flag. Success output can be suppressed by using the `--quiet` flag.
437
438To do a dry run without making any actual changes, use `--dry`.
439
440A regular expression may be used for the `from` parameter by specifying the `--isRegex` flag.
441
442The `from` and `to` parameters, as well as the files list, can be omitted if you provide this
443information in a configuration file. You can provide a path to a configuration file
444(either Javascript or JSON) with the `--configFile` flag. This path will be resolved using
445Node’s built in `path.resolve()`, so you can pass in an absolute or relative path.
446
447## A note on using globs with the CLI
448When using the CLI, the glob pattern is handled by the operating system. But if you specify the glob pattern in the configuration file, the package will use the glob module from the Node modules, and this can lead to different behaviour despite using the same pattern.
449
450For example, the following will only look at top level files:
451
452```js
453//config.js
454module.exports = {
455 from: /cat/g,
456 to: 'dog',
457};
458```
459
460```sh
461replace-in-file ** --configFile=config.js
462```
463
464However, this example is recursive:
465
466```js
467//config.js
468module.exports = {
469 files: '**',
470 from: /cat/g,
471 to: 'dog',
472};
473```
474
475```sh
476replace-in-file --configFile=config.js
477```
478
479If you want to do a recursive file search as an argument you must use:
480
481```sh
482replace-in-file $(ls l {,**/}*) --configFile=config.js
483```
484
485## Version information
486From version 3.0.0 onwards, replace in file requires Node 6 or higher. If you need support for Node 4 or 5, please use version 2.x.x.
487
488From version 5.0.0 onwards, replace in file requires Node 8 or higher. If you need support for Node 6, please use version 4.x.x.
489
490See the [Changelog](CHANGELOG.md) for more information.
491
492## License
493(MIT License)
494
495Copyright 2015-2020, Adam Reis, Co-founder at [Hello Club](https://helloclub.com/?source=npm)