Joe Gilmore

14 min read

NodeJS Re-naming Files scripts

Need a quick method of re-naming some files on your computer, then try flexing your coding muscles with some NodeJS scripts...

NodeJS Re-naming Files scripts

📝 Please note - these scripts have all been written to run on a Mac, I've not had chance to test them or edit them for Windows & Linux machines. They should only require small alterations to run however!

😱 A quick warning! Be careful when using any of these scripts as incorrect use could potentially delete files or make them un-useable! You have been warned!

1. Using Node JS to list files

So lets gets started with a really basic NodeJS script, one that can be run anywhere on your machine and doesn't require any packages to be installed. The script below simply lists files in a given directory. To use it save it somewhere on your computer as listing-files.js then run it with node listing-files.js in your terminal:

const fs = require('fs');
const path = require('path');

//List files within in a directory 
function listFiles(dir, callback) {
    fs.readdir(dir, (err, data) => {
        if (err) { return callback(err); }
        callback(null, data);
    });
}

listFiles('~/MyFolder', (err, data) => {
    if (err) { console.log(err); }
    console.log(data);
});

🤔 By the way... did you know that if you run your node js script like this: node listing-files.js > output.txt it will save the console logs to a file called "output.txt" instead of the console, and if you'd like both a text file and the console use node listing-files.js 2>&1 | tee output.txt

2. Renaming files sequentially with NodeJS:

In the first example we simply read files within a directory, in the next example we are going to expand on this and rename all of the files it finds but for safety reasons place the renamed files in a new folder and keep the original in-tact! Please note the destination must exist other wise an error will be thrown. I've also included an optional zeroPad function so the file names will look like 000001.jpg etc.

const fs = require('fs');
const path = require('path');

// Function to zero pad a number (optional but recommended)
function zeroPad(num, places) {
    var zero = places - num.toString().length + 1;
    return Array(+(zero > 0 && zero)).join("0") + num;
}

//Copy then rename files sequentially with a prefix
function copyRenameFiles(folderPath, newFolderPath, prefix) {
    fs.readdir(folderPath, (err, files) => {
        if (err) throw err;
        files.forEach((file, index) => {
            fs.copyFile(path.join(folderPath, file), path.join(newFolderPath, prefix + zeroPad(index+1,6) + '.jpg'), (err) => {
                if (err) throw err;
            });
        });
    });
}

copyRenameFiles('~/MyFiles', '~/MyRenamedFiles', 'myPrefix_')

3. Find and replace filenames with NodeJS

What if we have hundreds of files and there is something just not quite right with the filenames... instead of manually going through each file one by one (c'mon who hasn't done that at least once) instead we can use a script to rename our files in a much better way. In this instance I'm scanning a directory and replacing any files containing the string "ReplaceMe" with "NewString"

const fs = require('fs');
const path = require('path');

//Function to rename files in a given directory (But leaving the extension untouched)
function renameFilesSearchAndReplace(dir, search, replace) {
    fs.readdir(dir, function(err, files) {
        if (err) {
            return console.error(err);
        }
        files.forEach(function(file, index) {
            const ext = path.extname(file);
            const filenameNoExtension = path.basename(file, ext);
            const renamed = filenameNoExtension.replace(search, replace);
            if( !ext ){ return; }
            fs.rename(path.join(dir, file), path.join(dir, renamed + ext ), function(err) {
                if (err) {
                    return console.error(err);
                }
            });
        });
    });
}

renameFilesSearchAndReplace('~/MyFolder/', 'ReplaceMe', 'NewString');

4. List images within a given directory and create HTML Markup:

OK, this next example is a bit more complex as it includes an npm module: npm install exifreader and doesn't actually rename any files, but instead demonstrates how we can use NodeJS to list images with a given directory and create some basic HTML Markup for each image. Ideal for a blog article with some random images.

Simply replace the console.log with the HTML Markup you want to output and run the script:

const fs = require('fs');
const path = require('path');
const exifReader = require('exifreader');


//function to read list of images in a directory and read the filesize and image dimensions 
function readImages(dir) {
    const bytesToMegabytes = bytes => (bytes / 1024 / 1024).toFixed(2);
    fs.readdir(dir, function(err, files) {
        if (err) { return console.error(err); }
        files.forEach(function(file, index) {
            const filePath = path.join(dir, file);
            const dimensions = {};
            fs.stat(filePath, function(err, stats) {
                fs.readFile(filePath, function(err, data) {
                    const exifData = exifReader.load(data);
                    if(exifData['Image Width']){
                        dimensions.width = exifData['Image Width'].value;
                        dimensions.height = exifData['Image Height'].value;
                    }
                    console.log(`Filename: ${file}: Size: ${bytesToMegabytes(stats.size)}Mb, Resolution (WxH) : ${dimensions.width}px X ${dimensions.height}px`);
                })                
            });
        });
    });
}
readImages('~/MyPhotos/')

As you can see by using NodeJS we can easily manipulate file names on our Machine to do literally anything we want, the power behind running your own scripts to rename files is immense. But as Peter Parkers Uncles says "With great power comes great responsibility" - and that is especially true here! You can easily F🤬ck up big time, so be ultra careful.

Some things to note:

  • I had to write a script for my 3dnames.co website that created over 3 million files, I found I kept getting errors such as "Error: EMFILE: too many open files" and in the end I used this node-graceful-fs module as a drop in replacement for fs: const fs = require('graceful-fs'); and it definately seemed to handle it better than the regular fs module. For smaller lists of files however you'll find fs works fine.
  • Combining NodeJS scripting with a Service like AWS.S3() sync can be absolutely amazing if you fancy writing your own powerful backup scripts with cost effective savings!