Read/Write Files From Directory With Node.js

Published by in April, 2017

Categorized in: Dev Stuff

Tags: Node.js  

Perhaps you are looking for a way to dynamically read html files and update text on each page, like a file path with a build version number.

If that use case is what you are looking for, but in case you are just looking to see how Node.js can read files in a directory of a certain type, and then write to each file in the directory- I'll cover that here.

Let's start with an explanation of node modules I'm using.

I'm using node modules in the browser, and for that I'm using browserify. Then I'm using the following: the node.js built in file system module, the path module,  the semver module, and gulp for task running.

In my case I want to grab the version number from my package.json file and I'd like to take that version number, grab the major and minor from it, and write those files to my html which contains a build version number in the file path to browserify's bundle.js. This way every time I bump up my application version number in package.json, I don't have to manually bump up the version on each html page as well.

Let's build our gulpfile.js First require in the modules:


const gulp = require('gulp'),
      fs = require('fs'),
      path = require('path'),
      releaseVersion = JSON.parse(fs.readFileSync('./package.json')).version,
      semver = require('semver'),
      browserify = require('browserify');

Note how I retrieve the version number from package.json file by parsing the JSON and reading it with the file system module readFileSync method.

Next let's use the semver module. We will grab the releaseVersion variable and parse it with semver to get the major.minor number from it.


const buildPath = './build';
const buildVer = semver(releaseVersion);
const buildVersion = buildVer.major + '.' + buildVer.minor;
const buildVersionedPath = `./${buildPath}/${buildVersion}`;

Next we're going to read files from a directory using the file system readdir method.


fs.readdir('./some_directory_path', (err, files) => {});

Next we'll filter those files to only grab html files:


files.filter(function(file) { return file.substr(-5) === '.html'; })

Next we'll do a loop to for Node to begin reading each of those files.Note: each file path requires a url to the file in the directory


.forEach(file => {
        const filePath = path.join(__dirname + '/some_directory_pat/', file);

Next we use the file system readFile method for Node to read each file. And we set a variable for content that is a script tag:


fs.readFile(filePath, 'utf-8', function(err, content) {

          if (err) throw err;
          //find script tags
          var a = content.match(/([\s\S]*?)<\/script>/gmi);

In my case the only script file on my page is the browserified bundle.js file, so I know that it's the only one I need to modify.

Then for each matching script tag, we use the replace method for the text we want to replace on the page, and then the node file system method writeFile to write the replaced string to the page.


for(var i = 0; i < a.length; i++){
            const result = content.replace(a[i], '');
            //write result to page
            fs.writeFile(filePath, result, 'utf8', function (err) {
               if (err) return console.log(err);
            });
          }

That's all there is to it. The full gulp task is below, which you run with gulp file-version to begin the task:


const gulp = require('gulp'),
      fs = require('fs'),
      path = require('path'),
      releaseVersion = JSON.parse(fs.readFileSync('./package.json')).version,
      semver = require('semver'),
      browserify = require('browserify');

const buildPath = './build';
const buildVer = semver(releaseVersion);
const buildVersion = buildVer.major + '.' + buildVer.minor;
const buildVersionedPath = `./${buildPath}/${buildVersion}`;

gulp.task('file-version', function () {

  fs.readdir('./test', (err, files) => {
    console.log('\nModifying the build version number for the following:\n');
    files
      .filter(function(file) { return file.substr(-5) === '.html'; }) //filter only html files
      .forEach(file => {
        const filePath = path.join(__dirname + '/test/', file);
        console.log(file);
        fs.readFile(filePath, 'utf-8', function(err, content) {

          if (err) throw err;
          //find script tags
          var a = content.match(/([\s\S]*?)<\/script>/gmi);
          //console.log(a);
          for(var i = 0; i < a.length; i++){
            const result = content.replace(a[i], '');
            //write result to page
            fs.writeFile(filePath, result, 'utf8', function (err) {
               if (err) return console.log(err);
            });
          }
        });
    });
    console.log('\nModifying complete.')
  });
});