node.jsnpmnpm-scripts

How to rename file with npm script


I am using copyfiles as an npm scirpt copyfiles -u 2 /src/app/conf.dev.json dist/config/ but in the end I want to get the file renamed

How would you rename the input file in to something like conf.json ?

I check the docs and didn't find that it is possible to achieve with copyfiles. Any thoughts?

UPDATE: I follow up to this Rename file with NPM but getting an error when do npm run copy:

"copy": "copyfiles -u 2 /src/app/conf.dev.json dist/config/ && node -e require('fs').rename('dist/config/conf.prod.json','dist/config/conf.json')"

fs.js:137 throw new ERR_INVALID_CALLBACK(); ^

TypeError [ERR_INVALID_CALLBACK]: Callback must be a function


Solution

  • Below are a couple of solutions to successfully meet your requirement:

    Solution A

    As noted in @vitorlui's answer the callback parameter is mandatory when using the nodejs built-in fs.rename().

    Also when utilizing the node -e command via a npm script it is necessary to wrap the script to evaluate in JSON escaped double quotes, i.e. \"...\".

    1. For instance, configure the scripts section of your package.json as follows:

      "scripts": {
        "rename": "node -e \"require('fs').rename('dist/config/conf.dev.json', 'dist/config/conf.json', function(err) { if (err) console.log(err); console.log('File successfully renamed!') })\"",
        "copy": "copyfiles -u 2 \"src/app/conf.dev.json\" \"dist/config/\"",
        "copy-and-rename": "npm run copy && npm run rename"
      },
      
    2. Then run the following npm command:

      npm run copy-and-rename
      
    3. On successful completion you should see the following logged to the console after the file has been copied and renamed:

      File successfully renamed!


    Solution B

    You could also consider installing and utilizing renamer for renaming the file. This may be beneficial if your renaming requirements become more complex than the example provided in your question, or if you want something less verbose than Solution A.

    Install and check which version:

    1. cd to your project directory and install renamer by running the following command:

      npm i -D renamer
      
    2. Then run the following command to check which version of renamer was installed.

      npm ls renamer
      

    Note: The reason I ask you to check which version was installed is because this will determine which of the following renamer commands you should utilize. It differs slightly if the version installed is <0.7.0 or >=0.7.0:


    If the version of renamer installed is <0.7.0

    1. Set the scripts section of your package.json to the following:

      "scripts": {
        "rename": "renamer --dry-run -f --regex \"^conf.dev.json$\" -r \"conf.json\" \"dist/config/*\"",
        "copy": "copyfiles -u 2 \"src/app/conf.dev.json\" \"dist/config/\"",
        "copy-and-rename": "npm run copy && npm run rename"
      },
      
    2. Then run the following npm command:

      npm run copy-and-rename
      
    3. You should see something like the following logged to your console;

      āˆš dist\config\conf.dev.json -> dist\config\conf.json

      to indicate which pathname was changed.

    4. You'll also notice that the actual filename of the copied file hasn't changed, that's because we included the --dry-run option. Simply omit the --dry-run option from your script and run the command again for the actual file name to be changed.


    If the version of renamer installed is >=0.7.0

    There was a breaking change since v0.7.0 which included the removal of the --regex option (see here for further info). A regular expression literal is now provided since this version instead.

    This change to the API results in the rename script, (as previously shown), needing to be redefined as follows:

    "rename": "renamer -f \"/^conf.dev.json$/\" -r \"conf.json\" \"dist/config/*\"",
                            ^               ^
    

    Note: The --regex option has been omitted and a regexp is now a literal, i.e. it's now wrapped in a leading and trailing forward slash. Also, in this example the --dry-run option was removed, so reinstate it for testing purposes.


    Additional Notes