Exercise - Work with paths
As a developer at Tailwind Traders, you're about to enhance a program by using the Node.js path module and __dirname
global variable. This will allow the program to dynamically locate and process any .json files, regardless of where the program is run from.
Include the path module
At the top of your existing index.js file, include the path module.
const path = require("path");
Use the current directory
In the current index.js code, you're passing the static location of the stores folder. Let's change that code to use the __dirname
value instead of passing a static folder name.
In the
main
method, create a variable to store a path to the stores directory by using the__dirname
constant.async function main() { const salesDir = path.join(__dirname, "stores"); const salesFiles = await findSalesFiles(salesDir); console.log(salesFiles); }
Run the program from the command line.
node index.js
Notice that the path that's now listed for the files is the full system path, because the
__dirname
constant returns the full path to the current location.[ '/workspaces/node-essentials/nodejs-files/stores/201/sales.json', '/workspaces/node-essentials/nodejs-files/stores/202/sales.json', '/workspaces/node-essentials/nodejs-files/stores/203/sales.json', '/workspaces/node-essentials/nodejs-files/stores/204/sales.json' ]
Join paths
Instead of concatenating folder names to make a new path to search, you change the code to use the path.join
method. This code can then work across operating systems.
Change the
findFiles
method to usepath.join
.// previous code - with string concatentation const resultsReturned = await findSalesFiles(`${folderName}/${item.name}`); // current code - with path.join const resultsReturned = await findSalesFiles(path.join(folderName,item.name));
Run the program from the command line.
node index.js
The output is the same as the previous step, but the program is now more robust because it uses
path.join
instead of concatenating strings.
Find all .json files
Instead of looking for just sales.json files, the program needs to search for any file with an extension of .json. To do that, use the path.extname
method to check the filename extension.
Run the following command in the terminal to rename the stores/201/sales.json file to stores/sales/totals.json.
mv stores/201/sales.json stores/201/totals.json
In the
findSalesFiles
function, change theif
statement to check just the filename extension.if (path.extname(item.name) === ".json") { results.push(`${folderName}/${item.name}`); }
Run the program from the command line.
node index.js
The output now shows all the .json files in any of the store ID directories.
[ '/home/username/node-essentials/nodejs-files/stores/201/totals.json', '/home/username/node-essentials/nodejs-files/stores/202/sales.json', '/home/username/node-essentials/nodejs-files/stores/203/sales.json', '/home/username/node-essentials/nodejs-files/stores/204/sales.json' ]
Great job! You've used the path module and the __dirname
constant to make the program much more robust. In the next section, you'll learn how to create directories and move files between locations.
Got stuck?
If you got stuck at any point in this exercise, here's the completed code. Remove everything in index.js and replace it with this solution.
const fs = require("fs").promises;
const path = require("path");
async function findSalesFiles(folderName) {
// (1) Add an array at the top, to hold the paths to all the sales files that the program finds.
let results = [];
// (2) Read the currentFolder with the `readdir` method.
const items = await fs.readdir(folderName, { withFileTypes: true });
// (3) Add a block to loop over each item returned from the `readdir` method using the asynchronous `for...of` loop.
for (const item of items) {
// (4) Add an `if` statement to determine if the item is a file or a directory.
if (item.isDirectory()) {
// (5) If the item is a directory, recursively call the function `findSalesFiles` again, passing in the path to the item.
const resultsReturned = await findSalesFiles(path.join(folderName, item.name));
results = results.concat(resultsReturned);
} else {
// (6) If it's not a directory, add a check to make sure the item name matches *sales.json*.
if (path.extname(item.name) === ".json")
results.push(`${folderName}/${item.name}`);
}
}
return results;
}
async function main() {
const salesDir = path.join(__dirname, "stores");
// find paths to all the sales files
const salesFiles = await findSalesFiles(salesDir);
console.log(salesFiles);
}
main();