How to bulk convert file names using Node.js
By Flavio Copes
Learn how to bulk convert file names with a Node.js script that uses glob to find files and fs.copyFile to copy index.md files into slug-based names.
You can bulk convert file names with a short Node.js script. It finds the files with a glob pattern, computes the new name for each one, and copies or renames them with the fs module.
Here’s the real case where I needed this. I had to convert my folders structure from something like this:
posts/test/index.mdposts/hey-cool-post/index.md
to this:
posts/test.mdposts/hey-cool-post.md
removing the folder that contains an index.md file, and instead have the markdown file itself have the post slug (the part that’s used as the post URL).
I had hundreds of posts, so renaming by hand was not an option.
I used a Node.js script to do this. It relies on a glob pattern to find the files. You can test patterns like this in my glob pattern tester.
Install glob first:
npm install glob@13
Here it is:
import fs from 'node:fs/promises'
import { glob } from 'glob'
const root_folder = '.' //search in the current folder
const files = await glob(root_folder + '/**/index.md', { dotRelative: true })
for (const file_path of files) {
const match = file_path.match(/\/(.*?)\//)
const folder_name = match[1]
try {
await fs.copyFile(file_path, './' + folder_name + '.md')
console.log('File moved!')
} catch (err) {
console.log('Error Found:', err)
}
}
How the script works
node:fs/promises is the promise-based version of Node’s built-in fs module. The node: prefix makes it clear it’s part of Node, not an npm package.
The './**/index.md' pattern matches every index.md file, at any depth, starting from the current folder. glob returns a promise with the list of matching paths.
For each path, the regular expression /\/(.*?)\// captures the text between the first two slashes. For ./hey-cool-post/index.md that’s hey-cool-post, the folder name I want to use as the file name.
That’s why the script passes the dotRelative: true option to glob(). glob 13 returns paths like hey-cool-post/index.md, without the leading ./. Without that first slash, match is null and the script crashes. dotRelative puts the ./ back.
Then fs.copyFile() copies index.md to a new file named after its folder, in the current directory.
One thing to watch out for
fs.copyFile() copies, it doesn’t move. The original index.md files and their folders are still there after the script runs. I liked that, because I could check the result before deleting anything.
Once you’ve verified the new files, remove the old folders. Also, run this kind of script on a folder tracked by Git, so you can undo a wrong result with a checkout.
Want me to talk about your product? You can sponsor this site.
Related posts about node: