About
This article is about file system function in Node 1)
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`
Resolve vs Join
- resolve returns and resolve to an absolute path
- join will not and returns a relative path
Path relative to script path
- With import.meta.url
const scriptPath = new URL(import.meta.url).pathname.substring(1);
const scriptDirectory = path.dirname(scriptPath);
let srcFolder = path.resolve(scriptDirectory, 'src', 'components')
- With __dirname
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());
}
Get descendant files of a directory (read dir recursive)
- Sync
const readDirRecursive = (dir) => {
let returnedFiles = [];
fs
.readdirSync(dir)
.forEach((file) => {
const filepath = path.join(dir, file);
const stats = fs.statSync(filepath);
if (stats.isDirectory()) {
returnedFiles.concat(readDirRecursive(filepath));
} else {
returnedFiles.push(filepath);
}
});
return returnedFiles;
};
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
- 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
Get stat information (modification time, …)
How to get file stat information?
- with fs.statSync
let stats = fs.statSync("/dir/file.txt");
let mtime = stats.mtime;
Library
- Path in the browser: https://github.com/browserify/path-browserify
- Wrapper to add extra: https://github.com/jprichardson/node-fs-extra