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:
shelljs
find command to obtain the paths instead of ls. This will ensure the resulting paths include the base directories.filter
out 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 theshelljs
mv 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].html
to beTEST.html
we 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 renamer
Then use shelljs to invoke the
renamer
command.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-nodecli
Then invoke the
renamer
command as shown below:Note, using
shelljs-nodecli
you avoid manually looking into thenode_modules
directory to find the binaryrenamer
file. I.e.becomes...