As software developers, we often encounter repetitive tasks that can be automated to improve productivity and reduce errors. In this article, we will explore how to create our own file utility tool using Node.js. This tool will provide functionalities such as file copying, moving and deletion. Let's dive in!
Prerequisites
Before we begin, please ensure that you have Node.js and npm (Node Package Manager) installed on your computer. You can download the latest version of Node.js from the official website
Setting Up the Project
- Create a new project folder in your desired location.
- Open a command-line interface and navigate to the project folder.
- Run the following command to utilize a new Node.js project:
npm init -y
This will generate a package.json
file, which tracks the project's dependencies. We will circle back to this file later in the article for further modifications.
Installing Dependencies
Our utility tool will utilize the commander
package to handle command-line interactions. To install commander
, execute the following command in your project folder:
npm install commander
Implementing the Copy Command
Let's start by implementing the file copying functionality. We will use the fs
(File System) module provide by Node.js. Create a new file called index.js
in the root directory of your project and add the following code:
const fs = require("fs")
const path = require("path")
const { program } = require("commander")
program.version("1.0.0").description("File Utility Tool")
// Copy command
program
.command("copy <source> <destination>")
.description("Copy a file from the source path to the destination path")
.action((source, destination) => {
const sourcePath = path.resolve(source)
const destinationPath = path.resolve(destination)
const sourceStream = fs.createReadStream(sourcePath)
const destinationStream = fs.createWriteStream(destinationPath)
sourceStream.pipe(destinationStream)
sourceStream.on("end", () => {
console.log(`File copied from ${sourcePath} to ${destinationPath}`)
})
sourceStream.on("error", err => {
console.error("Error copying file:", err.message)
})
})
// Move command
// Delete command
program.parse(process.argv)
In the above code, we import the necessary modules fs
and path
for file operations, as well as the program
object from commander
. We define a copy
command that takes a source and destination file path as arguments.
Inside the copy
command, we resolve the provided paths to their absolute paths using path.resolve()
. This ensures that we are working with the correct file locations. We then create readable and writeable streams using fs.createReadStream()
and fs.createWriteStream()
respectively. By piping the source stream to the destination stream, we copy the file contents. Success and error messages are logged accordingly.
Lastly, the program.parse(process.argv)
line executes the utility tool from the command line. It parses the command-line arguments passed to the tools and invokes the corresponding actions defined for each command.
To test our copy implementation, let's create a file source.txt
in the project directory and add some content to it. You can use any text editor to create the file and add some text of your choice.
source.txt
This is the content of the source file.
Now, let's run the copy command to copy the contents of source.txt
to a new file called destination.txt
node index.js source.txt destination.txt
If everything works as expected, we should have a new file called destination.txt
created in the project directory with the same content as source.txt
.
Implementing the Move Command
Next, let's implement the file move functionality. Add the code below to index.js
:
// Move command
program
.command("move <source> <destination>")
.description("Move a file from the source path to the destination path")
.action((source, destination) => {
const sourcePath = path.resolve(source)
const destinationPath = path.resolve(destination)
fs.rename(sourcePath, destinationPath, err => {
if (err) {
console.error("Error moving file:", err.message)
} else {
console.log(`File moved from ${sourcePath} to ${destinationPath}`)
}
})
})
In the code snippet above, we define a move
command that takes two arguments: the source file path and the destination file path. Similar to the previous command, we resolve the provided paths to their absolute paths using path.resolve()
. We then use the fs.rename()
function to rename the source file to the destination path, effectively moving the file. Success and error messages are handled accordingly.
To test our move implementation, follow the steps we did for copy command. Create a file called source.txt
within the project directory and add some content to it.
Now, run the move command to move source.txt
to a new location called destination.txt
node index.js move source.txt destination.txt
If everything works as expected, source.txt
should be moved to the new location specified by destination.txt
. The original file source.txt
should no longer exist in the project directory.
Implementing the Delete Command
Lastly, let's implement the file deletion functionality. Add the following code to index.js
:
// Delete command
program
.command("delete <file>")
.description("Delete a file")
.action(file => {
const filePath = path.resolve(file)
fs.unlink(filePath, err => {
if (err) {
console.error("Error deleting file:", err.message)
} else {
console.log(`File deleted: ${filePath}`)
}
})
})
For the delete
command, it takes a single argument representing the file path. We resolve the provided path using path.resolve()
. Then, we use the fs.unlink()
function to delete the file at the specified path.
To test our delete implementation, follow the steps we did for copy command. Assuming you already have a source.txt
file in the project directory, run the delete command to delete the file:
node index.js delete source.txt
If everything works as expected, the file source.txt
should be deleted from the project directory.
⚠️ Warning: This action is irreversible!
Please note that this action is irreversible, so make sure you have a backup of any important files before running the delete command.
Testing Our Tool 🛠️
You can execute the utility tool by running the following command in your terminal or command prompt:
node index.js [command] [arguments]
Replace [command]
with the desired command (e.g., copy
, move
, or delete
) and provide the necessary [arguments]
based on the command you choose.
For example, to copy a file from source.txt
to destination.txt
you would run:
node index.js copy source.txt destination.txt
Similarly, for moving a file, you would run:
node index.js move source.txt destination.txt
And for deleting a file:
node index.js delete file.txt
Adjust the file names and path according to your specific requirements. The tool will execute the corresponding command and provide feedback in the console, such as success messages or error messages if any issues occur.
What's Next 💡?
That's it! The utility tool is now at your service. But wait, there's a bright idea that just sparked! Remember when I mentioned earlier that we would revisit the package.json file? Well, this is the perfect time. You see, although our tool is capable of some impressive feats, it's currently confined within the boundaries of our project folder. But don't worry, we have a clever solution to overcome this limitation and make our tool more versatile. Let's shed some light on how to expand its reach beyond the boundaries of our project folder
Making Our Tool Accessible Globaly
First, to make the tool work globally, we can package it as a global Node.js command-line tool. This will allow you to run the tool from any directory on your computer without needing to specify the path to the index.js
file.
Here's how you can make it work globally:
- Update
package.json
: Open yourpackage.json
file make sure it includes the following properties:
{
"name": "utilz",
"version": "1.0.0",
"description": "Utility tool for Copy, Move, and Delete operations",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": " <Your Name>",
"license": "MIT",
"bin": {
"utilz": "./index.js"
},
"preferGlobal": true,
"dependencies": {
"commander": "^10.0.1"
}
}
Update the values accordingly, including the name, description, author, and license. I named mine utilz
you can name yours whatever you want.
- *Add Shebang to
index.js
: At the very top of yourindex.js
file, add a shebang line to specify the interpreter for the file. For Node.js use the following line:
#!/usr/bin/env node
This line tells the operating system to use Node.js to interpret the script.
- Make
index.js
Executable: In your terminal or command prompt, navigate to the directory where yourindex.js
file is located. Run the following command to make the file executable:
chmod +x index.js
This command sets the executable permission for the index.js
file.
- Link the Package: Run the following command to globally link your utility tool:
npm link
This command creates a symbolic link from the globally installed directory to your utility tool's directory.
- Test the Global Tool: Now, you can use your utility tool globally from any directory. Open a new terminal or command prompt window, and you can run the tool using command
your-tool-name [command] [arguments]
.
For example, if I want to copy a file from any location, I can run the following command:
utilz copy my_old_file.txt new_destination.txt
VOILA! 🚀
Feel free to customize the tool further and add error handling, additional commands, or any other features to suit your specific needs. If you'd like to connect or have a chat, feel free to reach out to me on Twitter @geekreflex
Check out the repo
Conclusion
In this tutorial, we have built a file utility tool using Node.js and the commander
package. Our tool provides commands to copy, move, and delete files. By automating tasks, you can save time and simplify your development workflow, Utility tools like this can be expanded and customized based on your requirements, making you more productive as a programmer. Happy coding!