From 7260c898b6d43a558b07106daf4928069ce48755 Mon Sep 17 00:00:00 2001 From: Mansoor Munawar Date: Wed, 29 Jul 2026 02:50:44 +0100 Subject: [PATCH 1/2] Implemented cat,ls, and wc commant line tool. And also created an empty txt file to check my output for wc.mjs --- implement-shell-tools/cat/cat.mjs | 32 ++++++++++++++ implement-shell-tools/ls/ls.mjs | 22 ++++++++++ implement-shell-tools/wc/sample-files/4.txt | 0 implement-shell-tools/wc/wc.mjs | 48 +++++++++++++++++++++ 4 files changed, 102 insertions(+) create mode 100644 implement-shell-tools/cat/cat.mjs create mode 100644 implement-shell-tools/ls/ls.mjs create mode 100644 implement-shell-tools/wc/sample-files/4.txt create mode 100644 implement-shell-tools/wc/wc.mjs diff --git a/implement-shell-tools/cat/cat.mjs b/implement-shell-tools/cat/cat.mjs new file mode 100644 index 000000000..703e82763 --- /dev/null +++ b/implement-shell-tools/cat/cat.mjs @@ -0,0 +1,32 @@ +import process from "node:process"; +import { promises as fs } from "node:fs"; + +let args = process.argv.slice(2); +const flags = args.filter((arg) => arg.startsWith("-")); +const filePaths = args.filter((args) => !args.startsWith("-")); +let lineNumber = 1; + +for (const filePath of filePaths) { + const content = await fs.readFile(filePath, "utf-8"); + + if (flags.length == 0) { + process.stdout.write(content); + continue; + } + + const lines = content.split("\n"); + + for (const line of lines) { + if (flags.includes("-b")) { + if (line === "") { + console.log(); + } else { + console.log(`${lineNumber}\t${line}`); + lineNumber++; + } + } else if (flags.includes("-n")) { + console.log(`${lineNumber}\t${line}`); + lineNumber++; + } + } +} diff --git a/implement-shell-tools/ls/ls.mjs b/implement-shell-tools/ls/ls.mjs new file mode 100644 index 000000000..a0f2a5593 --- /dev/null +++ b/implement-shell-tools/ls/ls.mjs @@ -0,0 +1,22 @@ +import process from "node:process"; +import { promises as fs } from "node:fs"; + +const args = process.argv.slice(2); +const flags = args.filter((arg) => arg.startsWith("-")); +const path = args.filter((arg) => !arg.startsWith("-")); +let targetDir = path[0] || "."; +let files = await fs.readdir(targetDir); + +if (flags.includes("-a")) { + files.unshift(".", ".."); +} else { + files = files.filter((fileName) => !fileName.startsWith(".")); +} + +if (flags.includes("-1")) { + for (const file of files) { + console.log(file); + } +} else { + console.log(files.join(" ")); +} diff --git a/implement-shell-tools/wc/sample-files/4.txt b/implement-shell-tools/wc/sample-files/4.txt new file mode 100644 index 000000000..e69de29bb diff --git a/implement-shell-tools/wc/wc.mjs b/implement-shell-tools/wc/wc.mjs new file mode 100644 index 000000000..a63068dc9 --- /dev/null +++ b/implement-shell-tools/wc/wc.mjs @@ -0,0 +1,48 @@ +import process from "node:process"; +import { promises as fs } from "node:fs"; + +let filePaths = []; +let flag = null; +let numberOfWords; + +if (process.argv[2].startsWith("-")) { + flag = process.argv[2]; + filePaths = process.argv.slice(3); +} else { + filePaths = process.argv.slice(2); +} +for (const filePath of filePaths) { + const content = await fs.readFile(filePath, "utf-8"); + + if (flag === "-w") { + console.log(getWordCount(content)); + } else if (flag === "-l") { + console.log(getLineCount(content)); + } else if (flag === "-c") { + console.log(getByteCount(content), filePaths); + } else { + console.log( + getWordCount(content), + getLineCount(content), + getByteCount(content), + filePaths, + ); + } +} + +function getWordCount(text) { + const trimmed = text.trim(); + if (trimmed.length == 0) { + return 0; + } + return trimmed.split(/\s+/).length; +} + +function getLineCount(text) { + if (text.length == 0) return 0; + return text.split("\n").length - 1; +} + +function getByteCount(text) { + return Buffer.byteLength(text, "utf-8"); +} From b37eb2f14be00cc7a0d69eb4ad819b985baefebe Mon Sep 17 00:00:00 2001 From: Mansoor Munawar Date: Mon, 31 Aug 2026 23:09:15 +0100 Subject: [PATCH 2/2] implemented commander library to my cat, ls and wc file --- .DS_Store | Bin 0 -> 6148 bytes implement-shell-tools/.DS_Store | Bin 0 -> 6148 bytes implement-shell-tools/cat/cat.mjs | 53 ++++++++++----- implement-shell-tools/ls/ls.mjs | 45 ++++++++----- implement-shell-tools/package-lock.json | 25 +++++++ implement-shell-tools/package.json | 16 +++++ implement-shell-tools/wc/wc.mjs | 84 +++++++++++++++++------- 7 files changed, 166 insertions(+), 57 deletions(-) create mode 100644 .DS_Store create mode 100644 implement-shell-tools/.DS_Store create mode 100644 implement-shell-tools/package-lock.json create mode 100644 implement-shell-tools/package.json diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..9d00c88fe355a8ee309abe961ca9b18a1493cba2 GIT binary patch literal 6148 zcmeHKOHRW;41Iz9;kh239=opPc5%h9Eo$lywi-J;nDd{33;cBH8Qj}SI$g70;~446 zoRWcLAQ?yoPJjWu#3=I%$JEI{GLQ^>Goa@~VNZ}Ta_*Z literal 0 HcmV?d00001 diff --git a/implement-shell-tools/.DS_Store b/implement-shell-tools/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..a00719516cf91b3e1b4a5947b47214053c96a490 GIT binary patch literal 6148 zcmeH~Jr2S!425lAKw|00n1usyg9yP1xB#Mv35fwA)*PMZ9|j6Ds?f7!f3X{@?Hig} zM09gMtwlN!nZu2;vM?}3K9Ps?=hLk}UauD`q)n1mf_E~w{@O=U0V+TRr~nn90^?C2 zkMj9qJdeaDp#oH3BnsH~p}>tb*@FJ*K=2U&oT2Q7wa*e@u>x3=Er<$CqZN!+^)bZi z-VT=BSCcIm?V>q+Xx>?Eih*ggixwm>tquk%Km`U0Oe62?{NKU9&HsZIrc{6m{Fwqe z+wQj;yi}g8AFpTiLso6w;Gl0uc>4)JVn^{3?uP5d7GO=bASy8a2)GOkRN$uyJOQ!| B5HSD% literal 0 HcmV?d00001 diff --git a/implement-shell-tools/cat/cat.mjs b/implement-shell-tools/cat/cat.mjs index 703e82763..47651f179 100644 --- a/implement-shell-tools/cat/cat.mjs +++ b/implement-shell-tools/cat/cat.mjs @@ -1,32 +1,49 @@ import process from "node:process"; import { promises as fs } from "node:fs"; +import { program } from "commander"; + +program + .name("Cat") + .description("My version of cat command line tool") + .argument("", "Files to display") + .option("-n, --number", "Number all output lines") + .option("-b, --non-blank", "Number non empty output lines"); + +program.parse(); + +const { number, nonBlank } = program.opts(); +const filePaths = program.args; -let args = process.argv.slice(2); -const flags = args.filter((arg) => arg.startsWith("-")); -const filePaths = args.filter((args) => !args.startsWith("-")); let lineNumber = 1; for (const filePath of filePaths) { - const content = await fs.readFile(filePath, "utf-8"); + try { + const content = await fs.readFile(filePath, "utf-8"); - if (flags.length == 0) { - process.stdout.write(content); - continue; - } - - const lines = content.split("\n"); + if (!number && !nonBlank) { + process.stdout.write(content); + continue; + } + let text = content; + if (content.endsWith("\n")) { + text = content.slice(0, -1); + } + const lines = text.split("\n"); - for (const line of lines) { - if (flags.includes("-b")) { - if (line === "") { - console.log(); - } else { + for (const line of lines) { + if (nonBlank) { + if (line == "") { + console.log(); + } else { + console.log(`${lineNumber}\t${line}`); + lineNumber++; + } + } else if (number) { console.log(`${lineNumber}\t${line}`); lineNumber++; } - } else if (flags.includes("-n")) { - console.log(`${lineNumber}\t${line}`); - lineNumber++; } + } catch (error) { + console.error(`${error}`); } } diff --git a/implement-shell-tools/ls/ls.mjs b/implement-shell-tools/ls/ls.mjs index a0f2a5593..2c1574b4b 100644 --- a/implement-shell-tools/ls/ls.mjs +++ b/implement-shell-tools/ls/ls.mjs @@ -1,22 +1,37 @@ import process from "node:process"; import { promises as fs } from "node:fs"; +import { program } from "commander"; -const args = process.argv.slice(2); -const flags = args.filter((arg) => arg.startsWith("-")); -const path = args.filter((arg) => !arg.startsWith("-")); -let targetDir = path[0] || "."; -let files = await fs.readdir(targetDir); +program + .name("list") + .description("Implement my version of ls") + .argument("[paths...]", "The file path to process") + .option("-1, --one", "This list the item one per line") + .option("-a, --all", "This lists all of the files"); -if (flags.includes("-a")) { - files.unshift(".", ".."); -} else { - files = files.filter((fileName) => !fileName.startsWith(".")); -} +program.parse(); + +const { one, all } = program.opts(); +const paths = program.args; + +let targetDir = paths[0] || "."; + +try { + let files = await fs.readdir(targetDir); + + if (all) { + files = [".", "..", ...files].sort(); + } else { + files = files.filter((output) => !output.startsWith(".")).sort(); + } -if (flags.includes("-1")) { - for (const file of files) { - console.log(file); + if (one) { + for (const file of files) { + console.log(file); + } + } else { + console.log(files.join(" ")); } -} else { - console.log(files.join(" ")); +} catch (error) { + console.error(`${error}`); } diff --git a/implement-shell-tools/package-lock.json b/implement-shell-tools/package-lock.json new file mode 100644 index 000000000..5444e5c23 --- /dev/null +++ b/implement-shell-tools/package-lock.json @@ -0,0 +1,25 @@ +{ + "name": "implement-shell-tools", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "implement-shell-tools", + "version": "1.0.0", + "license": "ISC", + "dependencies": { + "commander": "^15.0.0" + } + }, + "node_modules/commander": { + "version": "15.0.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-15.0.0.tgz", + "integrity": "sha512-z67u4ZhzCL/Tydu1lJARtEZYWbWaN7oYLHbsuzocr6y4N6WZAagG3RQ4FW61V1/0+jImpj293XfrcYnd1qxtPg==", + "license": "MIT", + "engines": { + "node": ">=22.12.0" + } + } + } +} diff --git a/implement-shell-tools/package.json b/implement-shell-tools/package.json new file mode 100644 index 000000000..a05eb6f34 --- /dev/null +++ b/implement-shell-tools/package.json @@ -0,0 +1,16 @@ +{ + "name": "implement-shell-tools", + "version": "1.0.0", + "description": "Your task is to re-implement shell tools you have used.", + "main": "index.js", + "type": "module", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "keywords": [], + "author": "", + "license": "ISC", + "dependencies": { + "commander": "^15.0.0" + } +} diff --git a/implement-shell-tools/wc/wc.mjs b/implement-shell-tools/wc/wc.mjs index a63068dc9..65c86e9c5 100644 --- a/implement-shell-tools/wc/wc.mjs +++ b/implement-shell-tools/wc/wc.mjs @@ -1,33 +1,69 @@ import process from "node:process"; import { promises as fs } from "node:fs"; +import { program } from "commander"; -let filePaths = []; -let flag = null; -let numberOfWords; +program + .name("Word Count") + .description("my implementation of wc") + .argument("", "The file path to process") + .option("-l", "Count for the total number of lines") + .option("-c", "Count the total number of bytes") + .option("-w", "Count the total number of words"); + +program.parse(); + +let filePaths = program.args; +let options = program.opts(); +let noFlags = !options.l && !options.w && !options.c; + +let totalLines = 0; +let totalWords = 0; +let totalBytes = 0; -if (process.argv[2].startsWith("-")) { - flag = process.argv[2]; - filePaths = process.argv.slice(3); -} else { - filePaths = process.argv.slice(2); -} for (const filePath of filePaths) { - const content = await fs.readFile(filePath, "utf-8"); - - if (flag === "-w") { - console.log(getWordCount(content)); - } else if (flag === "-l") { - console.log(getLineCount(content)); - } else if (flag === "-c") { - console.log(getByteCount(content), filePaths); - } else { - console.log( - getWordCount(content), - getLineCount(content), - getByteCount(content), - filePaths, - ); + try { + const content = await fs.readFile(filePath, "utf-8"); + const outputs = []; + + const lines = getLineCount(content); + const words = getWordCount(content); + const bytes = getByteCount(content); + + totalLines += lines; + totalWords += words; + totalBytes += bytes; + + if (noFlags || options.l) { + outputs.push(lines); + } + if (noFlags || options.w) { + outputs.push(words); + } + if (noFlags || options.c) { + outputs.push(bytes); + } + + outputs.push(filePath); + console.log(outputs.join("\t")); + } catch (err) { + console.error(`${err.message}`); + } +} + +if (filePaths.length > 1) { + const totalOutputs = []; + + if (noFlags || options.l) { + totalOutputs.push(totalLines); + } + if (noFlags || options.w) { + totalOutputs.push(totalWords); + } + if (noFlags || options.c) { + totalOutputs.push(totalBytes); } + totalOutputs.push("total"); + console.log(totalOutputs.join("\t")); } function getWordCount(text) {