My Logo

PUBLISHED APRIL 18, 2024

Teghen Donald Ticha
Lastly Updated: 3 months ago
Reading time 18 mins

Working with Folders in NodeJS

Unlock the secrets of folder manipulation in Node.js! Explore essential techniques and methods for working with directories efficiently
Working with Folders in NodeJS

Prerequisite

Before diving in, some familiarity with basic nodeJS concepts would be a plus, although, not a requirement.
You may also benefit from this series part by reviewing the of this chapter.

Folder manipulation is a crucial aspect of file system operations, allowing developers to organize and manage their files efficiently.

First, we'll discuss Node.js' philosophy for folder manipulation and how it aligns with common practices across different operating systems.

Then, we'll explore various techniques for working with folders in Node.js, covering essential tasks such as checking folder existence, creating folders, reading folder contents, renaming folders, and removing folders.

Overview of Folder Manipulations

Different operating systems have their conventions and commands for folder manipulations. For instance, Linux uses commands like mkdir, ls, mv, and rm for creating, listing, moving, and removing folders, respectively.

Windows employs similar commands such as mkdir, dir, move, and rmdir, while macOS follows conventions similar to Linux.

NodeJS provides a platform-independent interface for performing folder operations, abstracting away the differences between operating systems and providing a consistent API for developers🤓.

Folder Manipulation in Node.js

NodeJS simplifies folder manipulation through, yet again, its built-in fs (File System) module, which offers methods for handling directories.

NodeJS follows a pragmatic approach to folder manipulation, providing intuitive methods that align with common practices across different operating systems.

Before devling into the various methods for manipulating folders, let's start with checking if a folder exists and and if we have access to it.

NB: If you intend on coding along while reading, then, in your current working directory, create a `test-folders` directory. All examples discussed will assume you have this folder ready!

How to check if folder exists and we have required access permissions

Before performing any folder manipulation operations, it's essential to check whether the target folder exists and if the current user has the necessary permissions to access it.

NodeJS provides methods like fs.existsSync() and fs.access() for this purpose.

  • fs.existsSync(): Synchronously checks if a directory exists.(NB: It's async counterpart fs.exists is deprecated)
  • fs.access(): Asynchronously checks the accessibility of a directory.
// index.js

const fs = require('fs');

// Check if folder exists synchronously
function folderExist(path_to_folder) {
    try {
        if (fs.existsSync(path_to_folder)) {
            return true;
        } 
        else {
            return false;
        }
    } catch (error) {
        console.log('An error occurred: ', error);
        return false;
    }
    
}   

function hasAccess (folderPath) {
    // check if folder exists
    if (!folderExist(folderPath)) {
        console.log('Folder doesn\'t exist');
        return
    }

    // Check folder accessibility asynchronously
    fs.access(folderPath, fs.constants.R_OK | fs.constants.W_OK, (err) => {
        if (err) {
            console.error('Folder is not accessible:', err);
        } 
        else {
            console.log('Folder is accessible.');
        }
    });
}

// Run the test
const folderPath = './test-folder';
hasAccess(folderPath);


NB: Don't forget to create an empty test-folder in the same directory as the index.js file where you run your code.

  • fs.existsSync() method that returns true if the directory exists and false otherwise.
  • fs.access() method that checks the accessibility of a directory based on the specified mode (fs.constants.R_OK for `read access` and fs.constants.W_OK for `write access`).

1. Creating Folders

Creating folders in NodeJS is straightforward using any of the following fs methods: fs.mkdir() or fs.mkdirSync() or fsPromises.mkdir(). These methods allows for the creation of both single and nested folders.

We'll illustrate using only the fs.mkdir() method and as practice, try refactoring the code to use the other two methods.

// index.js

const fs = require('fs');

const tesfolder = './test-folder';
const folderPath = tesfolder + '/path/to/new/folder';

// Create a new folder asynchronously using the callback pattern
fs.mkdir(folderPath, { recursive: true }, (err) => {
  if (err) {
    console.error('Error creating folder:', err);
  } else {
    console.log('Folder created successfully.');
  }
});
  • The fs.mkdir() method creates a directory at the specified path asynchronously.
  • The { recursive: true } option ensures that nested folders are created if the parent folders do not exist.
  • Run the code and check the `test-folder`, you have the following structure: test-folder/path/to/new/folder


2. Read Folders

Reading the contents of a folder in NodeJS can be achieved using the any of the following methods: fs.readdir() or fs.readdirSync() or fsPromises.readdir() .

These method returns an array of filenames contained within the specified directory.

As with folder create above, we'll illustrate using only the fs.readdir() method and as practice, try refactoring the code to use the other two methods.

// index.js

const fs = require('fs');

const testfolder = './test-folder';
const path1 = testfolder + '/path/to/folder';
const path2 = testfolder + '/path/to/new/folder';

const folderPaths = [path1, path2];

function test (paths) {
    paths.forEach(currPath => {
        console.log('\nReading path:', currPath, '\n');
        // Read folder contents asynchronously
        fs.readdir(currPath, (err, files) => {
            if (err) {
                console.error('Error reading folder contents:', err);
            } 
            else {
                console.log('The Following Files are found in folder:', currPath, ' : ',  files);
            }
        });
    })
}

// run test
test(folderPaths);
  • The fs.readdir() method reads the contents of the directory specified by folderPath.
  • Upon successful execution, the files array contains the names of all files and subdirectories within the specified directory.
  • Create a test.txt file in the /path/to/new/folder directory created from the previous example. Whe you run the code, you get a no such file or directory error for the first path and an array of files for the second.


3. Rename Folders

Renaming folders in NodeJS is achieved using these three methods fs.rename() methods: fs.rename() or fs.renameSync() or fsPromises.rename()

This method allows for the renaming of directories synchronously or asynchronously.

NB: The first parameter is the current path, the second the new path.

Again, as a practice, try using the other two methods not illustrated here.

// index.js

const fs = require('fs');

// file paths -> NB: create a test.txt file in the existing /path/to/new/folder directory
const testFolder = './test-folder';
const existingFilePath = testFolder + '/path/to/new/folder/test.txt';
const newFilePath = testFolder + '/path/to/new/folder/test_new.txt';

// folder paths : NB: create a test/t1 folder
const existingFolderPath = './test/t1'; 
const newFolderPath = './test/t2';


function run (oldPath, newPath) {
    // Rename path asynchronously
    fs.rename(oldPath, newPath, (err) => {
        if (err) {
            console.error('Error renaming folder:', err);
        } 
        else {
            console.log('Folder renamed successfully.');
        }
    });
}

// run test for file rename 
console.log('************************* Running test for file rename *************************');
run(existingFilePath, newFilePath);

// run test for folder rename
console.log('************************* Running test for folder rename *************************');
run(existingFolderPath, newFolderPath);

NB: create a `test.txt` file in the existing /path/to/new/folder directory and also create a test/t1 folder in a same directory with your index.js file.

Run the above and check the directory to confirm the changes.

In the case that the newPath already exists, it will be overwritten. If there is a directory at newPath, and you rename it to a file, an error will be raised instead.

4. Remove Folders

Removing folders in NodeJS is accomplished using these methods: fs.rmdir() or fs.rmdirSync() or fsPromises.rmdir().

These methods allows for the deletion of directories synchronously or asynchronously, with an optional recursive option to remove nested folders.

NB: To get a behavior similar to the rm -rf Unix command, use fs.rm() with options { recursive: true, force: true }.


To illustrate, let's remove the two folders (and their contents) created in the previous examples ie /test-folder and /test.

// index.js

const fs = require('fs');

// file paths -> NB: Make sure you have this directory:  test-folder
const folderPath1 = './test-folder';

// folder paths : NB: Make sure you have this directory: test 
const folderPath2 = './test';


function run (path_to_remove) {
    // Remove folder asynchronously
fs.rmdir(path_to_remove, { recursive: true }, (err) => {
    if (err) {
      console.error('Error removing path:', err);
    } else {
      console.log('Path removed successfully.');
    }
  });
}

// run test for file rename 
console.log('************************* Running test for file deletion *************************');
run(folderPath1);

// run test for folder rename
console.log('************************* Running test for folder deletion *************************');
run(folderPath2);


Extra:

In addition to fs.rmdir() for removing directories, the Node.js File System (fs) module provides another method for deleting files:


fs.unlink()

This method is used to asynchronously delete a file or symbolic link.

Let's have a short example: Create a `file.txt` in the same directory as your `index.js` file.

// index.js

const fs = require('fs');

const filePath = './file.txt';

// Delete file asynchronously
fs.unlink(filePath, (err) => {
    if (err) {
        console.error('Error deleting file:', err);
    }
    else {
        console.log('File deleted successfully.');
    }
});
  • The fs.unlink() method deletes the file specified by filePath.
  • It's important to note that this method will fail if the file does not exist or if the user does not have sufficient permissions to delete the file.


Use Case:
Use fs.unlink() when you need to delete a file asynchronously without considering the directory structure or recursive deletion.


Conclusion

In this series part, we've explored various techniques for working with folders in NodeJS. From checking folder existence and permissions to creating, reading, renaming, and removing folders, NodeJS provides a versatile set of methods for efficient folder manipulation.


Whether organizing project files, processing user uploads, or performing system maintenance tasks, mastering folder manipulation in Node.js is essential for building robust and scalable applications.

This marks the end of this chapter, in the next chapter, we'll discuss node's command line interface (CLI).

All Chapter Parts for NodeJs In Theory, An absolute Beginner’s Overview
  1. Chapter 1 , Part 1 : Introduction to NodeJS

    In this series part, I introduce nodeJS and some technical concepts associated with it. I also show how easy it is to setup and start a simple nodeJS web server.

  2. Chapter 1 , Part 2 : How to Install and Setup NodeJS

    In this series part, I run you through the various ways to install nodeJS. I also discuss how to install nvm and use it to switch between different node versions.

  3. Chapter 1 , Part 3 : How much JavaScript do you need to learn NodeJS

    In this series part, we explore the nuanced relationship between JavaScript and NodeJS, highlighting some subtle distinctions between the two environments.

  4. Chapter 1 , Part 4 : The v8 Engine and the difference Between NodeJS and the browser

    In this series part, we explore the V8 engine and how it interacts with nodeJS. We also discuss node’s event loop and uncover the mystery behinds node’s ability to handle concurrent operations.

  5. Chapter 1 , Part 5 : NPM, the NodeJS package manager

    Discover the essentials of npm, the powerful package manager for Node.js. Learn installation, management, publishing, and best practices

  6. Chapter 1 , Part 6 : NodeJS in Development Vs Production

    Explore how Node.js behaves differently in development and production environments. Learn key considerations for deploying Node.js applications effectively.

  7. Chapter 2 , Part 1 : Asynchronous Flow Control

    In this series part, we'll explore various aspects of asynchronous flow control in Node.js, from basic concepts to advanced techniques.

  8. Chapter 2 , Part 2 : Blocking vs Non-blocking I/O

    Explore the differences between blocking and non-blocking I/O in Node.js, and learn how to optimize performance and scalability.

  9. Chapter 2 , Part 3 : Understanding NodeJS Event loop

    Exploring the Node.js event loop by understanding its phases, kernel integration, and processes enabling seamless handling of asynchronous operations in your applications.

  10. Chapter 2 , Part 4 : The NodeJS EventEmitter

    Explore the power of Node.js EventEmitter: an essential tool for building scalable and event-driven applications. Learn how to utilize it effectively!

  11. Chapter 3 , Part 1 : Working with files in NodeJS

    Gain comprehensive insights into file management in Node.js, covering file stats, paths, and descriptors, to streamline and enhance file operations in your applications.

  12. Chapter 3 , Part 2 : Reading and Writing Files in NodeJS

    Uncover the fundamentals of reading and writing files in nodeJS with comprehensive examples and use cases for some widely used methods.

  13. Chapter 3 , Part 3 : Working with Folders in NodeJS

    Unlock the secrets of folder manipulation in Node.js! Explore essential techniques and methods for working with directories efficiently

  14. Chapter 4 , Part 1 : Running NodeJS Scripts

    Master the command line interface for executing nodeJS scripts efficiently. Learn common options and best practices for seamless script execution

  15. Chapter 4 , Part 2 : Reading Environment Variables in NodeJS

    Learn how to efficiently manage environment variables in nodeJS applications. Explore various methods and best practices for security and portability

  16. Chapter 4 , Part 3 : Writing Outputs to the Command Line in NodeJS

    Learn essential techniques for writing outputs in nodeJS CLI. From basic logging to formatting and understanding stdout/stderr.

  17. Chapter 4 , Part 4 : Reading Inputs from the Command Line in NodeJS

    Learn the various ways and strategies to efficiently read command line inputs in nodeJS, making your program more interactive and flexible.

  18. Chapter 4 , Part 5 : The NodeJS Read, Evaluate, Print, and Loop (REPL)

    Explore the power of nodeJS's Read, Evaluate, Print, and Loop (REPL). Learn how to use this interactive environment for rapid prototyping, debugging, and experimentation.

  19. Chapter 5 , Part 1 : Introduction to Testing in NodeJS

    Discover the fundamentals of testing in nodeJS! Learn about testing types, frameworks, and best practices for building reliable applications.

  20. Chapter 5 , Part 2 : Debugging Tools and Techniques in NodeJS

    Explore essential debugging tools and techniques in Node.js development. From built-in options to advanced strategies, and best practices for effective debugging.

  21. Chapter 6 , Part 1 : Project Planning and Setup

    Discuss the planning and design process for building our interactive file explorer in Node.js, focusing on core features, UI/UX design, and implementation approach and initial setup.

  22. Chapter 6 , Part 2 : Implementing Basic functionalities

    In this guide, we'll implement the basic functionalities of our app which will cover initial welcome and action prompts.

  23. Chapter 6 , Part 3 : Implementating Core Features and Conclusion

    In this guide, we'll complete the rest of the more advanced functionalities of our app including, create, search, sort, delete, rename and navigate file directories.