The __filename variable holds the absolute path to the currently executing file.
console.log('current filename', __filename)
the __dirname variable holds the absolute path to the directory that the currently executing file is in.
console.log('current dirname', __dirname)
The path.join() method joins all given path segments together using the platform-specific separator as a delimiter, then normalizes the resulting path.
const { join } = require('path')
console.log('out file:', join(__dirname, 'out.txt'))
The path.isAbsolute() method determines if path is an absolute path.
path.isAbsolute('/foo/bar'); // true
path.isAbsolute('/baz/..'); // true
path.isAbsolute('qux/'); // false
path.isAbsolute('.'); // false
Given two absolute paths, calculates the relative path between them.
path.relative('/data/orandea/test/aaa', '/data/orandea/impl/bbb');
// Returns: '../../impl/bbb'
Accepts multiple string arguments representing paths. Conceptually each path represents navigation to that path. The path.resolve function returns a string of the path that would result from navigating to each of the directories in order using the command line cd command.
path.resolve('/foo/bar', './baz');
// Returns: '/foo/bar/baz'
Resolves .. and . dot in paths and strips extra slashes.
path.normalize('/foo/../bar//baz');
// Returns: '/bar/baz'
Builds a string from an object. The object shape that path.format
accepts, corresponds to the object returned from path.parse
.
path.format({
root: '/',
name: 'file',
ext: '.txt'
});
// Returns: '/file.txt'
Returns an object whose properties represent significant elements of the path
path.parse('/home/user/dir/file.txt');
// Returns:
// { root: '/',
// dir: '/home/user/dir',
// base: 'file.txt',
// ext: '.txt',
// name: 'file' }
Returns the extension of the path
path.extname('index.html');
// Returns: '.html'
Returns the directory name of the path
path.dirname('/foo/bar/baz/asdf/quux');
// Returns: '/foo/bar/baz/asdf'
Returns the the last portion of the path
path.basename('/foo/bar/baz/asdf/quux.html');
// Returns: 'quux.html'
The higher level methods for reading and writing are provided in four abstraction types:
- Synchronous
- Callback based
- Promise based
- Stream based
const { readFileSync } = require('fs')
const contentsBuffer = readFileSync(__filename) // return Buffer
// OR
const contents = readFileSync(__filename, {encoding: 'utf8'}) // return string
writeFileSync(join(__dirname, 'out.txt'), contents.toUpperCase())
writeFileSync(join(__dirname, 'out.txt'), contents.toUpperCase(), {
flag: 'a'
}) // append
If there's a problem with an operation the *Sync APIs will throw. So to perform error handling they need to be wrapped in a try/catch.
const { join } = require('path')
const { readFile, writeFile } = require('fs')
readFile(__filename, {encoding: 'utf8'}, (err, contents) => {
if (err) {
console.error(err)
return
}
const out = join(__dirname, 'out.txt')
writeFile(out, contents.toUpperCase(), (err) => {
if (err) { console.error(err) }
})
})
const { join } = require('path')
const { readFile, writeFile } = require('fs').promises
async function run () {
const contents = await readFile(__filename, {encoding: 'utf8'})
const out = join(__dirname, 'out.txt')
await writeFile(out, contents.toUpperCase())
}
run().catch(console.error)
const { pipeline } = require('stream')
const { join } = require('path')
const { createReadStream, createWriteStream } = require('fs')
pipeline(
createReadStream(__filename),
createWriteStream(join(__dirname, 'out.txt')),
(err) => {
if (err) {
console.error(err)
return
}
console.log('finished writing')
}
)
fs module provides multiple ways to read a directory:
- Synchronous
- Callback based
- Promise based
- An async iterable that inherits from fs.Dir
const { readdirSync, readdir } = require('fs')
const { readdir: readdirProm } = require('fs').promises
try {
console.log('sync', readdirSync(__dirname))
} catch (err) {
console.error(err)
}
readdir(__dirname, (err, files) => {
if (err) {
console.error(err)
return
}
console.log('callback', files)
})
async function run () {
const files = await readdirProm(__dirname)
console.log('promise', files)
}
run().catch((err) => {
console.error(err)
})
Metadata about files can be obtained with the following methods:
- fs.stat, fs.statSync, fs.promises.stat
- fs.lstat, fs.lstatSync, fs.promises.lstat
The only difference between the stat
and lstat
methods is that stat
follows symbolic links, and lstat
will get meta data for symbolic links instead of following them.
const { readdirSync, statSync } = require('fs')
const files = readdirSync('.')
for (const name of files) {
const stat = statSync(name)
const typeLabel = stat.isDirectory() ? 'dir: ' : 'file: '
const { atime, birthtime, ctime, mtime } = stat
console.group(typeLabel, name)
console.log('atime:', atime.toLocaleString())
console.log('ctime:', ctime.toLocaleString())
console.log('mtime:', mtime.toLocaleString())
console.log('birthtime:', birthtime.toLocaleString())
console.groupEnd()
console.log()
}
There are four stats available for files:
- Access time
- Change time
- Modified time
- Birth time
const { watch } = require('fs')
watch('.', (evt, filename) => {
console.log(evt, filename)
})
The listener callback gets two arguments (eventType, filename). eventType is either 'rename' or 'change', and filename is the name of the file which triggered the event.