Prerequisite
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 counterpartfs.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 returnstrue
if the directory exists andfalse
otherwise. - ➢
fs.access()
method that checks the accessibility of a directory based on the specified mode (fs.constants.R_OK
for `read access` andfs.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 byfolderPath
. - ➢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 anarray 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 thenewPath
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 therm -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()
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 byfilePath
. - ➢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).
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.
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.
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.
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.
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
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.
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.
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.
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.
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!
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.
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.
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
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
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
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.
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.
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.
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.
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.
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.
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.
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.