Skip to content
Open
38 changes: 38 additions & 0 deletions implement-shell-tools/cat/cat.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { program } from "commander";
import process from "node:process";
import { promises as fs } from "node:fs";

let showNumber = false;

program
.name("cat")
.description("Prints the output of a file to the console")
.option("-n, --number", "Displays the lines along with their number")
.argument("<path>", "The file path")
.allowExcessArguments();
program.parse();

const argv = program.args;
if (argv.length < 1) {
console.error(
`Expected exactly 1 or more arguments (paths) to be passed but got ${argv.length}.`,
);
process.exit(1);
}

showNumber = program.opts().number;

const stringArr = [];
for (const path of argv) {
stringArr.push(await fs.readFile(path, "utf-8"));
}

const flatArr = stringArr.flatMap((l) =>
l
.split("\n")
.map((l, i, a) => (i < a.length - 1 ? l + "\n" : l))
.filter((l) => l !== ""),
);

if (!showNumber) console.log(flatArr.join(""));
else console.log(flatArr.map((l, i) => `${i + 1} ${l}`).join(""));
25 changes: 25 additions & 0 deletions implement-shell-tools/cat/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

15 changes: 15 additions & 0 deletions implement-shell-tools/cat/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"name": "cat",
"version": "1.0.0",
"description": "You should already be familiar with the `cat` command line tool.",
"license": "ISC",
"author": "",
"type": "module",
"main": "cat.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"dependencies": {
"commander": "^14.0.3"
}
}
36 changes: 36 additions & 0 deletions implement-shell-tools/ls/ls.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { program } from "commander";
import process from "node:process";
import fs from "node:fs";

let vertical = false;
let showHidden = false;

program
.name("list-directory-contents")
.description("Shows all files and folders in a directory")
.option("-1", "List one file/directory per line")
.option("-a, --all", "Show hidden files")
.argument("[path]", "Path of the directory to list (defaults to .)");

program.parse();

const argv = program.args;

vertical = program.opts()[1];
showHidden = program.opts().all;

const folderPath = argv[0] || ".";

const contents = fs.readdirSync(folderPath);

const filtered = contents.filter((f) => f[0] !== ".");

const dirArr = !showHidden ? filtered : contents;

if (!vertical) {
console.log(dirArr.join(" "));
} else {
for (const content of dirArr) {
console.log(content);
}
}
25 changes: 25 additions & 0 deletions implement-shell-tools/ls/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 16 additions & 0 deletions implement-shell-tools/ls/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"name": "ls",
"version": "1.0.0",
"description": "You should already be familiar with the `ls` command line tool.",
"main": "ls.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"type": "module",
"dependencies": {
"commander": "^14.0.3"
}
}
25 changes: 25 additions & 0 deletions implement-shell-tools/wc/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 16 additions & 0 deletions implement-shell-tools/wc/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"name": "wc",
"version": "1.0.0",
"description": "You should already be familiar with the `wc` command line tool.",
"main": "wc.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"type": "module",
"dependencies": {
"commander": "^14.0.3"
}
}
72 changes: 72 additions & 0 deletions implement-shell-tools/wc/wc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import { program } from "commander";
import process from "node:process";
import { promises as fs } from "node:fs";

let showLineCount = true;
let showWordCount = true;
let showByteCount = true;

program
.name("wc")
.description(
"Print the number of lines, word and bytes for each file and a total if there are multiple files",
)
.option("-l, --lines", "Print the number of lines")
.option("-w, --words", "Print the number of words")
.option("-c, --bytes", "Print the number of bytes")
.argument("<path>", "The file path")
.allowExcessArguments();
program.parse();

const argv = program.args;

if (Object.keys(program.opts()).length >= 1) {
showLineCount = program.opts().lines;
showWordCount = program.opts().words;
showByteCount = program.opts().bytes;
}

const stringArr = [];
for (const path of argv) {
stringArr.push(await fs.readFile(path, "utf-8"));
}

let lines = 0;
let words = 0;
let bytes = 0;

const infoArr = [];
for (let i = 0; i < stringArr.length; i++) {
const arr = [];
const line = stringArr[i].split("\n").length;
const wc = stringArr[i].split(" ").flatMap((l) =>
l
.split("\n")
.map((l, i, a) => (i < a.length - 1 ? l + "\n" : l))
.filter((l) => l.trim() !== ""),
).length;
const lineByte = new Blob([stringArr[i]]).size;
if (showLineCount) {
arr.push(line - 1);
lines += line - 1;
}
if (showWordCount) {
arr.push(wc);
words += wc;
}
if (showByteCount) {
arr.push(lineByte);
bytes += lineByte;
}
arr.push(argv[i]);
infoArr.push(arr.join(" "));
}

if (infoArr.length > 1) {
const totalArr = ["total"];
if (showByteCount) totalArr.unshift(bytes);
if (showWordCount) totalArr.unshift(words);
if (showLineCount) totalArr.unshift(lines);
infoArr.push(totalArr.join(" "));
}
console.log(infoArr.join("\n"));
Loading