Introduction
This article discusses how you can determine if a path is a subdirectory of another in NodeJS. If you would like to follow along with this tutorial make sure you have NodeJS installed and if not go ahead and follow this installation tutorial to set it up.
The Problem
We want to determine if a path is subdirectory of another directory. For example, if you have two paths, /blog/category
and /blog/category/node
, you should return true as /blog/category/node
is a subdirectory of /blog/category
. On the other hand, /blog/category
and /news/category/node
should not return true. Essentially, we want to check whether a path is a child of a parent path.
Before discussing how to go about the solution, let us first see how the NodeJS path module works.
NodeJS Path Module
The NodeJS path module provides utilities for working with paths in NodeJS. It provides different methods you can use to easily manipulate and analyze file paths. Since it is included in the standard library, you can use it without installation.
const path = require('path')
The following section covers some of the common path methods.
path.relative()
This method is used to find the relative path from one given path to another. It accepts two paths; the path `from` which is the base path and the path `to` which is used to find the relative path. If the paths are the same, path.relative()
returns a zero-length string.
path.relative( from, to )
Consider the following code that uses path.relative()
const relPath1 = path.relative("blog/category", "blog/write");
console.log(relPath1)// output: ../write
const relPath2 = path.relative("blog/category", "post/node-path-module");
console.log(relPath2)// output: ../../post/node-path-module
// When both the paths are same
// It returns blank string
const relPath3 = path.relative("blog/category", "blog/category");
console.log(relPath3) // output: returns a zero length string as paths are the same
path.isAbsolute()
path.isAbsolute()
is used to check whether or not a particular path is an absolute one or not. An absolute path refers to a path that contains all the details required to locate a file in a file system starting from the root element and ending with the other subdirectories. This method accepts one parameter that accepts the path to the file being checked if it's absolute. If the path is absolute, it returns true, if not it returns false.
path.isAbsolute( path )
Below is an example of path.isAbsolute()
in use.
const absPath1 = path.isAbsolute('/foo/bar');
console.log(absPath1) // Output: true
const absPath2 = path.isAbsolute('/baz/..');
console.log(absPath2) // Output: true
const absPath3 = path.isAbsolute('qux/');
console.log(absPath3) // Output: false
const absPath4 = path.isAbsolute('.');
console.log(absPath4) // Output: false
As illustrated, the path.isAbsolute()
method returns a boolean that indicates whether the path is absolute or not.
path.Normalize()
Sometimes paths are written in shortcuts that include .. and . to make navigation easier. However, writing a long path like this can lead to readability issues which can then lead to human error. path.Normalize()
is used to convert the paths with these shortcuts to actual paths with all the details included. This method accepts a string representing the path to be normalized as a parameter. The return value is a string of the normalized path.
path.normalize( path )
Below is an example of how to use path.Nomalize()
const normPath1 = path.normalize("/blog/category/.");
console.log(normPath1)// output: /blog/category
const normPath2 = path.normalize("/blog/../node");
console.log(normPath2) //output: /node
const normPath3 = path.normalize("/blog///admin///comments")
console.log(normPath3); // output: /blog/admin/comments
That's it! Those are some of the methods available on the path module. There are more methods than this and you should look at the documentation to learn more about them. This article only covered the methods that will be used in the solution below when determining if a subdirectory is a child of another directory.
Set Up NodeJS
Now that you know how to work with the path module, you can now proceed to the solution. In your preferred working directory, create a new file and name it ‘node-path.js
’. Now you will need to set up a simple server to help you in your functions. Open the file you just created in your text editor and add the following code.
const http = require("http");
const requestListener = function (req, res) {
res.end("Hello, World!");
};
const server = http.createServer(requestListener);
server.listen(3000);
To run your application, use the following command
node node-path.js
Using NodeJS Path
The NodeJS path is a module that provides the necessary utilities for working with files in NodeJS. To add it to your application, you do not need to import it since it comes with the standard library. Simply add it to your file using the following line of code.
const path = require('path');
Consider the following solution.
const http = require("http");
const path = require('path');
function checkIfSubDir (parent, dir) {
const relative = path.relative(parent, dir);
return relative && !relative.startsWith('..') && !path.isAbsolute(relative);
}
pathsToTest.forEach((paths) => {
console.log(checkIfSubDir(paths[0], paths[1]))
})
const requestListener = function (req, res) {
res.end("Hello, World!");
};
const server = http.createServer(requestListener);
server.listen(3000);
Let’s understand the above code. In the first line, you are importing the path module. This provides the methods that will be used to analyze the directory paths.
Next, you are declaring a function that accepts the parent directory path and the path to be evaluated.
The function works on the premise that if the child is a subdirectory of the parent, the relative path from the parent to the child will always start with '..
'. The path.relative()
method accepts two paths and returns the relative path from the ‘from’ directory to the ‘to’ directory. If the child is inside the parent, the relative path from the former to the latter will always start with '..
'.
To test this solution, try passing the following paths to your function.
[
['/foo', '/foo'],
['/foo', '/bar'],
['/foo', '/foobar'],
['/foo', '/foo/bar'],
['/foo', '/foo/../bar'],
['/foo', '/foo/./bar'],
['/bar/../foo', '/foo/bar'],
['/foo', './bar'],
['C:\\Foo', 'C:\\Foo\\Bar'],
['C:\\Foo', 'C:\\Bar'],
['C:\\Foo', 'D:\\Foo\\Bar']
];
You should expect the following solution.
false
false
true
false
true
true
false
false
false
false
The above solution will help you check whether a directory is a child of another directory. It is the perfect solution if you also want it to work on Windows.
Recap
In this article, you learned how to use the NodeJS path module to determine whether a NodeJS path is a subdirectory of another. The article started by first defining the problem that needed to be solved then gave a brief overview of the NodeJS path module. Finally, the article discussed the solution which checked to see if the relative path from the parent to the child started with '..
'.
The solution to this problem is inspired by a StackOverflow solution to the same problem. If you want to learn more about the path module, do so by reviewing the NodeJS path documentation.