Code Monkey home page Code Monkey logo

replace-in-files's Introduction

replace-in-files

Replace text in one or more files or globs. Works asynchronously with promises.

npm version dependencies Status Build Status Coverage Status

Installation

# Using npm
npm install replace-in-files

# Using yarn
yarn add replace-in-files

Usage

Specify options

const replaceInFiles = require('replace-in-files');

const options = {
  // See more: https://www.npmjs.com/package/globby
  // Single file or glob
  files: 'path/to/file',
  // Multiple files or globs
  files: [
    'path/to/file',
    'path/to/other/file',
    'path/to/files/*.html',
    'another/**/*.path',
  ],


  // See more: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace
  // Replacement
  from: /foo/g,  // string or regex
  to: 'bar', // string or fn  (fn: carrying last argument - path to replaced file)


  // See more: https://www.npmjs.com/package/glob
  optionsForFiles: { // default
    "ignore": [
      "**/node_modules/**"
    ]
  }


  // format: `${fileName}-${year}-${month}-${day}_${hour}:${minute}:${second}.{fileExtension}`
  //            fileName-2017-11-01_21:29:55.js
  // date of createFile old file or last modificate (if not find create date)
  saveOldFile: false // default


  //Character encoding for reading/writing files
  encoding: 'utf8',  // default


  shouldSkipBinaryFiles: true, // default
  onlyFindPathsWithoutReplace: false // default
  returnPaths: true // default
  returnCountOfMatchesByPaths: true // default
};

Replacing multiple occurrences

Please note that the value specified in the from parameter is passed straight to the native String replace method. As such, if you pass a string as the from parameter, it will only replace the first occurrence.

To replace multiple occurrences at once, you must use a regular expression for the from parameter with the global flag enabled, e.g. /foo/g.

Asynchronous replacement with promises

const replaceInFiles = require('replace-in-files');

// ...

replaceInFiles(options)
  .then(({ changedFiles, countOfMatchesByPaths }) => {
    console.log('Modified files:', changedFiles);
    console.log('Count of matches by paths:', countOfMatchesByPaths);
    console.log('was called with:', options);
  })
  .catch(error => {
    console.error('Error occurred:', error);
  });

Asynchronous replacement with co yield

const replaceInFiles = require('replace-in-files');
const co = require('co');

// ...

co(function* () {
  const {
    changedFiles,
    countOfMatchesByPaths,
    replaceInFilesOptions
  } = yield replaceInFiles(options);
  console.log('Modified files:', changedFiles);
  console.log('Count of matches by paths:', countOfMatchesByPaths);
  console.log('was called with:', replaceInFilesOptions);
}).catch((error) => {
  console.log('Error occurred:', error);
});

Asynchronous replacement with async await (node 8+)

const replaceInFiles = require('replace-in-files');

// ...

async function main() {
  try {
    const {
      changedFiles,
      countOfMatchesByPaths,
      replaceInFilesOptions
    } = await replaceInFiles(options);
    console.log('Modified files:', changedFiles);
    console.log('Count of matches by paths:', countOfMatchesByPaths);
    console.log('was called with:', replaceInFilesOptions);
  } catch (error) {
    console.log('Error occurred:', error);
  }
}

main();

Sequentially replacement

use .pipe - will be replaced with only files found at first replacement

.pipe supported only: { from, to } (the other options will be received from options in the first replacement)

const replaceInFiles = require('replace-in-files');

// ...

async function main() {
  try {
    const {
      changedFiles,
      countOfMatchesByPaths,
      replaceInFilesOptions
    } = await replaceInFiles(options)
      .pipe({ from: 'foo', to: 'bar' })
      .pipe({ from: 'first', to: 'second' })
      .pipe({ from: /const/g, to: () => 'var' });
    console.log('Modified files:', changedFiles);
    console.log('Count of matches by paths:', countOfMatchesByPaths);
    console.log('was called with:', replaceInFilesOptions);
  } catch (error) {
    console.log('Error occurred:', error);
  }
}

main();

Return value

The return value of the library is an object with: countOfMatchesByPaths and paths

For example:

const replaceInFiles = require('replace-in-files');

const data = replaceInFiles({
  files: 'path/to/files/*.html',
  from: 'a',
  to: 'b',
});

// data could like:
{
  countOfMatchesByPaths: [
    {
      'path/to/files/file1.html': 5,
      'path/to/files/file3.html': 1,
      'path/to/files/file5.html': 3
    }
  ],
  paths: [
    'path/to/files/file1.html',
    'path/to/files/file3.html',
    'path/to/files/file5.html',
  ],
  replaceInFilesOptions: [
    {
      files: 'path/to/files/*.html',
      from: 'a',
      to: 'b',
    }
  ]
}

// if empty:
{
  countOfMatchesByPaths: [
    {}
  ],
  paths: []
}

// if used 2 .pipe
{
  countOfMatchesByPaths: [
    {
      'path/to/files/file1.html': 5,
      'path/to/files/file3.html': 1,
      'path/to/files/file5.html': 3
    },
    {
      'path/to/files/file5.html': 4
    },
    {
      'path/to/files/file1.html': 2,
      'path/to/files/file5.html': 4
    }
  ],
  paths: [
    'path/to/files/file1.html',
    'path/to/files/file3.html',
    'path/to/files/file5.html',
  ],
  replaceInFilesOptions: [
    {
      files: 'path/to/files/*.html',
      from: 'a',
      to: 'b',
    },
    {
      from: 'c',
      to: 'd',
    },
    {
      from: 'e',
      to: 'f',
    }
  ]
}

Version information

  • Replace in files requires Node 12 or higher. (v.3.0.0 +) potentially still supported earlier node, but in pipeline eslint required node >=12
  • Replace in files requires Node 8 or higher. (v.2.0.3) - potentially still supported node 6, but in pipeline eslint required node 8
  • Replace in files requires Node 6 or higher. (v.1.1.4)

License

(MIT License)

replace-in-files's People

Contributors

bertyhell avatar dependabot[bot] avatar ibcwilljust42 avatar shhdharmen avatar wj42ftns avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

replace-in-files's Issues

Replace patterns with $ don't work

string.replace allows patterns like '$1' in the to string to refer to capture groups. These patterns don't work in this library. Instead, the literal string '$1' is inserted.

Replacing text to nothing doesn't work (thus removing). Also undefined as changedFiles result

Tested as node script on Windows (11) with the following options:

replacing: style="display:inline;fill:XXXX"

Not working:

const options = {
    files: '../src/assets/vectors/**/*',
    // from: /hallo?/g,
    from: /display:.*;/g,
    to: '',
}

But this does actually work:

const options = {
    files: '../src/assets/vectors/**/*',
    // from: /hallo?/g,
    from: /display:.*;/g,
    to: ' ',
}

Also the changedFiles param from the readme example write undefined in both cases.

Modified files: undefined
Count of matches by paths: [ { '../src/assets/vectors/dealer_word.svg': 10 } ]
was called with: { files: '../src/assets/vectors/**/*', from: /display:.*;/g, to: ' ' }

Empty "to" value

Hello! Simple issue: most important feature for replacing (at least for me) it's changing value from some string to empty string.
If I trying to do something like:
let options = { files: ['../src/*', '../src/**/*'], from: /test/gm, to: "" }
I always have only occurrences in result, but files not changing.
Node version: v11.5.0
Package version: Latest at the moment.

Thanks in advance!

Would be good to document how to do a function replace using a regexp

I tried to use your library using a regexp find and function replace, but spent 20 minutes getting my head round the options and console logging stuff to see what I needed to do. Eventually I gave up and I ended up writing a glob and doing it myself.

This was my use case - converting tags (with ml- prefix) from snake-case to PascalCase:

const Fs = require('fs')
const glob = require('glob')

// options
const options = { encoding:'utf8' }

// start
glob('./src/**/*.vue', function (er, files) {
  // debug
  console.log(`Processing ${files.length} files...`)

  // process files
  files.forEach(file => {
    // variables
    let count = 0
    const text = Fs.readFileSync(file, options)

    // replacement
    const output = text.replace(/<\/?ml-[\w-]+/g, function (match, pos, all) {
      count += 1
      return match
        .replace(/-\w/g, m => m.slice(1).toUpperCase())
        .replace('ml', 'Ml')
    })

    // if replacements were made
    if (count) {
      Fs.writeFileSync(file, output, options)
      console.log(count, file)
    }
  })
})

With your lib I just didn't know what the replace function's arguments were, so specifically documenting an example would make it less ambiguous.

Thanks

Corrupted image files

Hello! Thanks for your work on this package, it's been very helpful for my work.

I'm running into an issue where running the package on a directory with images cause those files to become corrupted. I've created a simplified example to make it easier to test.

To reproduce:

  • git clone [email protected]:zachwolf/replace-in-files-reduces-test-case.git
  • cd replace-in-files-reduces-test-case
  • npm i
  • npm start
  • git status

Notice that the favicon is now reporting a binary diff, and it can not be opened by browsers.

Screen Shot 2019-04-30 at 3 56 44 PM

I know that there are options and glob matches to work with this already provided. It would be very helpful if the default behavior only ran replace on string-like content. I'm not sure what the use case would be for replacing in image files intentionally.

Thanks again!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.