When creating content experiences, I like to use Node.js for light housekeeping, by which I mean little chores that streamline the process. Things like:

  • Detecting files added to (or removed from) source repositories.
  • Parsing TOC (table of contents) index files to stage pages to the right places.
  • Repairing broken comment markup prior to generating reference pages.
  • Repairing broken content spit out by reference page generators.
  • Updating configuration files for build scripts and tools (e.g. Apache ant).
  • Generating index pages, tag clouds, and other supporting content.

These tasks frequently require a list of files located in a particular directory and its child directories. Here's one way to develop such a list:

// very basic command line handling.
var strFilePath = process.argv[ 2 ];
if ( ( strFilePath == null ) || ( strFilePath == "" ) || 
     ( strFilePath == undefined ) ) {
   console.log( "Declaration error: Target folder not specified." );
   return;
}

// Normalize and verify the input parameter value
var p = require( "path" );
var strFilePath = p.resolve( strFilePath ); 
var fs = require( "fs" );
var pathStat = fs.statSync( strFullFilename );
if ( pathStat.isDirectory() == false ) {
   console.log( "Declaration error: '" + 
                strFullFilename + "' is not a folder." );
   return;
}

// Prepare the result object
var oResults = new Object;
oResults.paths = [];
oResults.paths.push( strFilePath );
oResults.files = [];

// Scan every folder found; make sure we can them all
for ( var xDir = 0; xDir < ( oResults.paths.length ); xDir++ ) {
  var sCurrDir = oResults.paths[ xDir ];
  var aThisDir = fs.readdirSync( sCurrDir );

  for ( var xThisFile = 0; xThisFile < ( aThisDir.length ); xThisFile++ ) {

     var strFullFilename = sCurrDir + "/" + aThisDir[ xThisFile ];
     var xTFStat = fs.statSync( strFullFilename );

     if ( xTFStat.isFile() ) {
       oResults.files.push( strFullFilename );
     } else { if ( xTFStat.isDirectory() ) {
       oResults.paths.push( strFullFilename );
     } else {
       console.log( "Skipping ", strFullFilename, "; not a file or folder." );
     } }
  } 
}

console.log( JSON.stringify( oResults, undefined, 3 ) );

This example verifies the parameter value supplied by the caller. Unless a valid directory is provided, an error appears and the script ends.

The target directory is scanned and each file tested. Individual filenames are added to the files property array and child directories are added the paths property array. Because the outer loop relies on paths, child directories are processed.

You'll notice the file evaluation block includes an else for unexpected results.

When the outer loop completes, the oResults object is ready for the next step.

Mind you, there are easier ways to generate a list of files, including a simple shell command:

$ find ~/projects/mydocsite/_site -name "*.html" > filelist.txt

If that's all you need, the shell command is obviously the better choice. However, if you have more complicated processing in mind, Node's value becomes more apparent. We'll come back to this in future posts.

Vital stats

First posted: 4 February 2017; tested using Node.js v7.4.0.