I have this file structure:
FolderName/
[NAME]/
[NAME].controller.js
[NAME].html
Using Node.js I want to replace [NAME] with a variable.
Here is what I've tried:
const shell = require("shelljs");
shell.ls('-Rl', '.').forEach(entry => {
if (entry.name.includes(`[NAME]`)) {
let newName = entry.name.replace(/\[NAME\]/, "Test");
shell.mv(entry.name, newName);
}
});
This will only rename the folder [NAME] to Test, and leave the files untouched. And output this:
mv: no such file or directory: FolderName/[NAME]/[NAME].controller.js
mv: no such file or directory: FolderName/[NAME]/[NAME].html
The issue
When running
shell.mv(entry.name, newName);within the context of your example its trying to move/change a path that no longer exists as it has been changed in a previous turn of the loop. This results in the error:Solution A
To avoid the error try the following approach:
shelljsfind command to obtain the paths instead of ls. This will ensure the resulting paths include the base directories.filterout any paths whose asset does not contain the string to find (e.g[NAME]. Also exclude any hidden assets (i.e. those names starting with a dot.)[NAME]) with the replacement string (e.gTEST) within each path. Then finally apply the new path using theshelljsmv command.Note: As a safeguard, (at step 4), the asset/path is only renamed if the new resultant path is not already taken. If the new path DOES already exist then those paths that should not be renamed are reported. For example, To better understand this, lets assume we have an initial directory structured as follows:
Initial directory structure.
...If we run the script searching for the string
[NAME]to be replaced with the stringTEST- then we have a potential problem. If we were to rename[NAME].htmlto beTEST.htmlwe would override the existingTEST.html. Our resultant directory would be structured as follows:Potential resultant directory structure.
By only renaming an asset if the new resultant path IS NOT already taken we avoid this potentially harmful scenario of loosing data.
Actual resultant directory structure.
When an asset should not be renamed, (as it would result in loss of data), the script currently reports those instances. Given the initial directory structure (above) the following will be logged to your console:
The following gist uses the approach described above. The solution is authored in ES5 so it works with older versions of nodejs, however it can be simply revised to use the ES6 syntax.
example node script 1
Solution B
Your requirement can also be achieved by installing and utilizing renamer.
$ npm i -D renamerThen use shelljs to invoke the
renamercommand.example node script 2
example node script 3
If you need something a little more terse, (although it incurs an additional dependency), you could utilize shelljs-nodecli:
$ npm i -D shelljs-nodecliThen invoke the
renamercommand as shown below:Note, using
shelljs-nodecliyou avoid manually looking into thenode_modulesdirectory to find the binaryrenamerfile. I.e.becomes...