Building a File Utility Tool with Node.js

May 19, 2023

🕒8 mins

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

  1. Create a new project folder in your desired location.
  2. Open a command-line interface and navigate to the project folder.
  3. 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:

  1. Update package.json: Open your package.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.

  1. *Add Shebang toindex.js: At the very top of your index.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.

  1. Make index.js Executable: In your terminal or command prompt, navigate to the directory where your index.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.

  1. 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.

  1. 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!


Profile picture

Hello, I'm Jerry Nwosu.
I build stuff on the internet.

rss