Node - File System

About

Example

Rename files in a directory

The below code will rename all files if the suffix contains a number.

Ex: from blue_oregon_x90.svg to blue_oregon.svg

Steps:

  • select only the files in a directory
  • select only the files with a svg extension
  • select only the files where the last part contains a number. Example: blue_oregon_x90.svg would be selected
  • then create the new name and rename
fs = require('fs');
path = require('path');

dir = 'gallery\\composite\\illustrations';
fs.readdirSync(dir)
    .map(file => path.join(dir, file))
    .filter(p => fs.statSync(p).isFile())
    .filter(p => path.extname(p) == ".svg" )
    .filter(p => {
        baseName = path.basename(p);
        lastPart = baseName.substring(baseName.lastIndexOf("_"));
        result = lastPart.match(/[0-9]/g);
        return result != null;
    })
    .forEach(p => {
        baseName = path.basename(p);
        newName = path.join(dir, baseName.substr(0, baseName.lastIndexOf("_")))+".svg";
        fs.renameSync(p,newName);
        console.log("Renamed to "+newName);
    });

Management

There is two API for file system operations:

  • Path to manipulate path string
  • file system to perform operations on the file system with the path

Path

Path operations are described here: https://nodejs.org/api/path.html

Full Qualified Path

var path = require("path");
var absolutePath = path.resolve("./path"); // Relative file path

Get Directory and file name

const path = require('path')

// basename:
//   * for a file, the filename with the extension `hello.md`, 
//   * for a directory the last name
filename = path.basename(base); 

dirname = path.dirname(base); // the directory name 
extname = path.extname(base); // the extension ie `.md`
filenameWithoutExtension = path.basename(base,​ path.extname(base));​ // `hello`

Path relative to script path

path.join(__dirname, '.', '.env');

File System

The file system library can be found at https://nodejs.org/api/fs.html

Get children files of a directory

export function getFiles(dir) {

    return fs.readdirSync(dir)
        .map(file => path.join(dir, file))
        .filter(path => fs.statSync(path).isFile());

}

IsDirectory / isFile

const isDirectory = source => fs.lstatSync(source).isDirectory();
const isFile = source => fs.lstatSync(source).isFile();

Traversal

An example of a traversal script that will ignore the file or directory defined in a gitignore file with the ignore package.

const path = require('path');
const fs = require('fs');
const ignore = require('ignore');
const ig = ignore()
    .add(fs.readFileSync('.gitignore').toString())
    .add(".git");

async function processDir(rootDir, srcDir, dstDir) {
    try {
       // This is a traversal request, it returns all level
        let dirEntries = fs.readdirSync(srcDir, {
            encoding: 'utf8',
            withFileTypes: true
        });
        for (let e of dirEntries) {
            if (e.isDirectory()) {
                let newSrc = path.join(srcDir, e.name); // String as arg, string returned
                let relativeSrc = path.relative(rootDir, newSrc)
                if (!ig.ignores(relativeSrc)) {
                    processDir(rootDir, newSrc);
                    console.log("* process dir   : " + e.name + " (" + path.resolve(srcDir, e.name) + ")");
                } else {
                    console.log("(ignored dir   : " + newSrc+")");
                }
            } else if (e.isFile()) {
                if (ig.ignores(e.name)) {
                    console.log("(ignored file  : " + e.name+")")
                } else {
                    console.log("  * processed file : " + e.name)
                }
            } else {
                console.log(`process: File ignored: ${e.name} not a regular file`);
            }
        }
    } catch (err) {
        throw new Error(err);
    }
}

const src = path.join(__dirname, '.');
processDir(src, src);

Exist

  • path (synchronous call) and with fs.stats
const fs = require('fs')
let dirExists = fs.existsSync(dirPath) && fs.lstatSync(dirPath).isDirectory();
let fileExists = fs.existsSync(dirFile) && fs.lstatSync(dirFile).isFile();
  • Path (Asynchronous)
const fs = require('fs')
fs.access(path, fs.F_OK, (err) => {
  if (err) {
    console.error(err)
    return
  }
  // File exit
})

Rename

Ref

  • An Synchronous rename
oldName = "dir/file.ext";
newName = "dir/file.csv";
fs.renameSync(oldName,newName);

Read File

Example when reading a JSON.

const dataObject = JSON.parse(fs.readFileSync('data/file.json'));

Write file

In a async with promisify

await util.promisify(fs.writeFile)('./dir/file.json', JSON.stringify(object, null, ' '));

Watch

/**
 * From @xprudhomme.
 * Check if file exists, watching containing directory meanwhile.
 * Resolve if the file exists, or if the file is created before the timeout
 * occurs.
 * @param {string} filePath
 * @param {integer} timeout
 * @returns {!Promise<undefined>} Resolves when file has been created. Rejects
 *     if timeout is reached.
 */
function waitForFileExists(filePath, timeout=15000) {
  return new Promise((resolve, reject) => {
    const dir = path.dirname(filePath);
    const basename = path.basename(filePath);

    const watcher = fs.watch(dir, (eventType, filename) => {
      if (eventType === 'rename' && filename === basename) {
        clearTimeout(timer);
        watcher.close();
        resolve();
      }
    });

    const timer = setTimeout(() => {
      watcher.close();
      reject(new Error(' [checkFileExists] File does not exist, and was not created during the timeout delay.'));
    }, timeout);

    fs.access(filePath, fs.constants.R_OK, err =>  {
      if (!err) {
        clearTimeout(timer);
        watcher.close();
        resolve();
      }
    });
  });
}

Extract from verify_download.js


Powered by ComboStrap