One of the built-in features of Node.js is the manipulation of the operating system's file system using the fs module. This Node.js module contains many useful functions for working with files and directories.

Files are simply referred to as persisted objects or chunks of data that are typically stored on a hard medium known as a disk or memory. Files can be of various types, from text files to image files, audio files, and many more.

So, what is a file system, and how can you easily interact with an operating system's file system in Node.js?

What Is a File System?

A file system defines how an operating system can identify, organize, store, and access files, along with other operations.

The file system of an operating system also does the job of grouping files into collections known as directories or folders. Ordinary files and directories are the most common parts of a file system that are often interacted with among many others.

Some examples of file systems include New Technology File System (NTFS), UNIX File System (UFS), and Hierarchical File System (HFS).

What Is the Node.js fs Module?

The Node.js fs module is a built-in library provided by Node.js for working with the file system of any operating system that supports Node. The fs module is easily accessible and is the go-to library for file operations like reading from files or writing data to files in Node.js.

It is very commonly used with the path and os modules to perform various operations on files. To use the fs module in your programs, you can import it into your source code as shown in the code below.

        // CommonJS
const fs = require('fs')
 
// ES6
import fs from 'fs'

What Is the Node.js path Module?

You can use the Node.js path module to manipulate file paths. It includes utilities for easily interacting with file and directory paths. Using the fs and path modules in tandem to complete a task is standard practice. This is because the majority of fs module functions depend on paths to target files or directories to function.

You can import the path module into your code with the syntax below:

        // CommonJS
const path = require('path')
 
// ES6
import path from 'path'

Common Functions for Accessing the File System in Node.js

Here are the most commonly used Node.js fs and path module functions, and how to use them to interact with files and directories.

Working With Paths

  1. path.resolve: This is the function for resolving a path from a list of path instructions passed as parameters. For example:
            path.resolve('home', 'projects', 'web');
    // returns <path_to_current_directory>/home/projects/web
     
    path.resolve('home/projects/web', '../mobile');
    // returns <path_to_current_directory>/home/projects/mobile
  2. path.normalize: The normalize function returns the correct and normalized path from a given input path. For example:
            path.normalize('home/projects/web/../mobile/./code');
    // returns home/projects/mobile/code
  3. path.join: This function builds a path out of several segments. For example:
            path.join('home', 'projects', '../', 'movies');
    // returns home/movies
  4. path.basename: The basename function returns the final path segment. You can use it in two ways:
            path.basename('home/projects/web/index.js');
    // returns index.js
     
    path.basename('home/projects/web/index.js', '.js');
    // removes the extension and returns 'index'
  5. path.dirname: This function returns the path to the last directory of a given path. Example:
            path.dirname('home/projects/web/index.js');
    // returns home/projects/web
  6. path.extname: With this function, you can get the extension of a file from a given path.
            path.extname('home/projects/web/index.js');
    // returns '.js'

Opening and Closing Files

  1. fs.open: This is the function for opening or creating a file synchronously in Node.js. The synchronous form of fs.open is fs.openSync. fs.open accepts four arguments which are the file path, flags, open mode, and a callback function. Flags and open mode have a default value, and you may learn more about them from the Node.js fs.open documentation.
            const filePath = path.join(__dirname, '/videos/newVideo.mp4');
    // __dirname returns the path to the current working directory.
    // filePath = <path_to_current_directory>/videos/newVideo.mp4
     
    fs.open(filePath, (error, fileDescriptor) => {
        // handle errors
        console.log(fileDescriptor); // prints an integer representing the file descriptor
    })
  2. fs.close: It is good practice to always close any open files when they are no longer needed. Node.js has the fs.close function for this:
            fs.open(filePath, (error, fileDescriptor) => {
        // handle errors, such as 'file/directory does not exist'
        console.log(fileDescriptor);
     
        // close the file
        fs.close(fileDescriptor, (error) => {
            // handle errors
            console.log('File closed successfully');
        });
    })

Creating and Deleting

  1. fs.mkdir: This works just like the mkdir terminal command which creates a new directory. It takes in a path, mode (optional), and callback function as parameters. You can use it like this:
            const dirPath = path.join(__dirname, 'newDirectory');

    fs.mkdir(dirPath, (error) => {
        // handle errors
        console.log('New directory created successfully');
    });
  2. fs.unlink: This function removes or deletes the file at the path passed in as an argument. Consider the code example below:
            const filePath = path.join(_dirname, 'oldFile.js');
     
    fs.unlink(filePath, (error) => {
        // handle errors
        console.log('File has been deleted successfully');
    });
  3. fs.rmdir: This method deletes the directory at a given path. It's very similar in usage to the unlink method:
            const dirPath = path.resolve('home', 'projects', 'web');
     
    fs.rmdir(dirPath, (error) => {
        // handle errors
        console.log('Directory successfully deleted');
    })

File Metadata

  1. fs.exists: The exists method checks if the file at a given path exists. The implementation is as follows:
            let filePath = path.join(__dirname, 'index.html');
     
    fs.exists(filePath, (exists) => {
        console.log(exists) // true or false
    })
  2. fs.stat: This is a synchronous function that returns the properties of a file. It returns an fs.Stats object which exposes some methods for accessing the properties of the file. Here's an example:
            fs.stat('index.js', (error, stats) => {
        console.log(stats); // prints low level properties of the file
        stats.isFile(); // returns true
        stats.isDirectory(); // returns false
    })

You should use the path methods when working with file paths as they save you from unexpected behavior across platforms. The Node.js fs and Node.js path documentation describe an exhaustive list of methods.

Manipulating the File System in Node.js

The vastness of the fs module makes it very easy to access and interact with files on any operating system. When you use it together with the path module, you are open to more functionality and can manipulate the file system as you want.

A major advantage of Node.js is its portability. You can develop your apps on any platform and deploy them anywhere without worrying about basic compatibility issues.