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
Below are a couple of solutions to successfully meet your requirement:
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. \"...\"
.
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"
},
Then run the following npm command:
npm run copy-and-rename
On successful completion you should see the following logged to the console after the file has been copied and renamed:
File successfully renamed!
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.
cd
to your project directory and install renamer
by running the following command:
npm i -D renamer
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:
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"
},
Then run the following npm
command:
npm run copy-and-rename
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.
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.
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.
For both Solution A and Solution B, the copying and renaming logic has been added to separate npm scripts, (namely copy
and rename
respectively) for clarity of explanation. However you can chain the two commands using the &&
operator instead to form one npm script - the single line will be rather long though :)
For Solution B, I often utilize version 0.6.1
of renamer
, so I run; npm i -D renamer@0.6.1
to install, as I typically have older versions of nodejs to support. In which case I utilize the --regex
flag as per the example shown in the aforementioned sub section titled: "If the version of renamer installed is <0.7.0".