From 7faa4609ec232993801e756bfbdfa74445c866bb Mon Sep 17 00:00:00 2001 From: Fatma Date: Wed, 30 Jul 2025 23:40:33 +0100 Subject: [PATCH 1/7] Set up package.json and install Commander - Added "type": "module" to package.json - Installed commander as a dependency --- implement-shell-tools/package-lock.json | 25 +++++++++++++++++++++++++ implement-shell-tools/package.json | 16 ++++++++++++++++ 2 files changed, 41 insertions(+) create mode 100644 implement-shell-tools/package-lock.json create mode 100644 implement-shell-tools/package.json diff --git a/implement-shell-tools/package-lock.json b/implement-shell-tools/package-lock.json new file mode 100644 index 00000000..35bb20ea --- /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": "^14.0.0" + } + }, + "node_modules/commander": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-14.0.0.tgz", + "integrity": "sha512-2uM9rYjPvyq39NwLRqaiLtWHyDC1FvryJDa2ATTVims5YAS4PupsEQsDvP14FqhFr0P49CYDugi59xaxJlTXRA==", + "license": "MIT", + "engines": { + "node": ">=20" + } + } + } +} diff --git a/implement-shell-tools/package.json b/implement-shell-tools/package.json new file mode 100644 index 00000000..809da8b9 --- /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": "^14.0.0" + } +} From 4283d1f7641e23527886631d850a2398890462be Mon Sep 17 00:00:00 2001 From: Fatma Date: Wed, 30 Jul 2025 23:44:32 +0100 Subject: [PATCH 2/7] Implement cat command --- implement-shell-tools/cat/cat.js | 36 ++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 implement-shell-tools/cat/cat.js diff --git a/implement-shell-tools/cat/cat.js b/implement-shell-tools/cat/cat.js new file mode 100644 index 00000000..a0071a65 --- /dev/null +++ b/implement-shell-tools/cat/cat.js @@ -0,0 +1,36 @@ +import { program } from "commander"; +import { promises as fs } from "node:fs"; + +program + .name("my-cat") + .description("Reimplementation of the Unix `cat` command with -n and -b support") + .option("-n", "number all lines") + .option("-b", "number non-empty lines") + .argument("", "files to read"); + +program.parse(); + +const options = program.opts(); +const filePaths = program.args; + +let lineNumber = 1; + +for (const filePath of filePaths) { + const content = await fs.readFile(filePath, "utf-8"); + + for (const line of content.split("\n")) { + if (options.n) { + console.log(`${lineNumber} ${line}`); + lineNumber++; + } else if (options.b) { + if (line.trim()) { + console.log(`${lineNumber} ${line}`); + lineNumber++; + } else { + console.log(""); + } + } else { + console.log(line); + } + } +} From 1ee815e4c481e07cdeb47ad461789bf5c4d1fe9c Mon Sep 17 00:00:00 2001 From: Fatma Date: Thu, 31 Jul 2025 00:40:32 +0100 Subject: [PATCH 3/7] Implement ls command --- implement-shell-tools/ls/ls.js | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 implement-shell-tools/ls/ls.js diff --git a/implement-shell-tools/ls/ls.js b/implement-shell-tools/ls/ls.js new file mode 100644 index 00000000..d4d6a4fd --- /dev/null +++ b/implement-shell-tools/ls/ls.js @@ -0,0 +1,24 @@ +import { program } from "commander"; +import { promises as fs } from "node:fs"; + +program + .name("my-ls") + .description("Reimplementation of the Unix `ls` command with -1 and -a options") + .option("-1", "list one file per line") + .option("-a", "include hidden files") + .argument("[directory]", "directory to list"); + +program.parse(); + +const options = program.opts(); + +const directory = program.args[0] || "."; // Use current directory as default if no argument is provided + +const files = await fs.readdir(directory); + +const visibleFiles = options.a ? files : files.filter(file => !file.startsWith(".")); + +for (const file of visibleFiles) { + console.log(file); +} + \ No newline at end of file From 61122dab7c5850d3ae79b717b8821362cf8009ad Mon Sep 17 00:00:00 2001 From: Fatma Date: Thu, 31 Jul 2025 01:00:51 +0100 Subject: [PATCH 4/7] Implement wc command --- implement-shell-tools/wc/wc.js | 57 ++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 implement-shell-tools/wc/wc.js diff --git a/implement-shell-tools/wc/wc.js b/implement-shell-tools/wc/wc.js new file mode 100644 index 00000000..b5b2ac9a --- /dev/null +++ b/implement-shell-tools/wc/wc.js @@ -0,0 +1,57 @@ +import { program } from "commander"; +import { promises as fs } from "node:fs"; + +program + .name("my-wc") + .description("Reimplementation of the Unix `wc` command supporting -l, -w, and -c flags") + .option("-l", "show line count") + .option("-w", "show word count") + .option("-c", "show character count") + .argument("", "files to read"); + +program.parse(); + +const options = program.opts(); +const filePaths = program.args; + +let totalLines = 0; +let totalWords = 0; +let totalChars = 0; + +for (const filePath of filePaths) { + const content = await fs.readFile(filePath, "utf-8"); + + const lineCount = content.split("\n").length; + const wordCount = content.trim().split(/\s+/).length; + const charCount = content.length; + + totalLines += lineCount; + totalWords += wordCount; + totalChars += charCount; + + let output = ""; + + if (options.l || options.w || options.c) { + if (options.l) output += `${lineCount} `; + if (options.w) output += `${wordCount} `; + if (options.c) output += `${charCount} `; + } else { + output += `${lineCount} ${wordCount} ${charCount} `; + } + + console.log(`${output}${filePath}`); +} + +if (filePaths.length > 1) { + let totalOutput = ""; + + if (options.l || options.w || options.c) { + if (options.l) totalOutput += `${totalLines} `; + if (options.w) totalOutput += `${totalWords} `; + if (options.c) totalOutput += `${totalChars} `; + } else { + totalOutput += `${totalLines} ${totalWords} ${totalChars} `; + } + + console.log(`${totalOutput}total`); +} From ba120facba8de80d1bb320489dd6c88b70902e4f Mon Sep 17 00:00:00 2001 From: Fatma Date: Sun, 17 Aug 2025 21:26:54 +0100 Subject: [PATCH 5/7] fix: Align line numbers --- implement-shell-tools/cat/cat.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/implement-shell-tools/cat/cat.js b/implement-shell-tools/cat/cat.js index a0071a65..9aa0fabf 100644 --- a/implement-shell-tools/cat/cat.js +++ b/implement-shell-tools/cat/cat.js @@ -20,11 +20,11 @@ for (const filePath of filePaths) { for (const line of content.split("\n")) { if (options.n) { - console.log(`${lineNumber} ${line}`); + console.log(`${String(lineNumber).padStart(6, ' ')} ${line}`); lineNumber++; } else if (options.b) { if (line.trim()) { - console.log(`${lineNumber} ${line}`); + console.log(`${String(lineNumber).padStart(6, ' ')} ${line}`); lineNumber++; } else { console.log(""); From 6f08d18da1804477a41677d6852fe6443e1e6954 Mon Sep 17 00:00:00 2001 From: Fatma Date: Sun, 17 Aug 2025 21:53:23 +0100 Subject: [PATCH 6/7] feat: Show files in one line if -1 option is not used --- implement-shell-tools/ls/ls.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/implement-shell-tools/ls/ls.js b/implement-shell-tools/ls/ls.js index d4d6a4fd..cdccb524 100644 --- a/implement-shell-tools/ls/ls.js +++ b/implement-shell-tools/ls/ls.js @@ -18,7 +18,11 @@ const files = await fs.readdir(directory); const visibleFiles = options.a ? files : files.filter(file => !file.startsWith(".")); -for (const file of visibleFiles) { - console.log(file); +if (options["1"]) { + for (const file of visibleFiles) { + console.log(file); + } +} else { + console.log(visibleFiles.join(" ")); } \ No newline at end of file From e5788f804a27cb64a1899dbd615f21ea5512ad82 Mon Sep 17 00:00:00 2001 From: Fatma Date: Sun, 17 Aug 2025 23:09:54 +0100 Subject: [PATCH 7/7] refactor: Simplify output formatting and fix line count calculation --- implement-shell-tools/wc/wc.js | 36 ++++++++++++++++------------------ 1 file changed, 17 insertions(+), 19 deletions(-) diff --git a/implement-shell-tools/wc/wc.js b/implement-shell-tools/wc/wc.js index b5b2ac9a..197d8d10 100644 --- a/implement-shell-tools/wc/wc.js +++ b/implement-shell-tools/wc/wc.js @@ -14,6 +14,20 @@ program.parse(); const options = program.opts(); const filePaths = program.args; +function formatCounts(lines, words, chars, options) { + let result = ""; + + if (options.l || options.w || options.c) { + if (options.l) result += `${lines} `; + if (options.w) result += `${words} `; + if (options.c) result += `${chars} `; + } else { + result += `${lines} ${words} ${chars} `; + } + + return result; +} + let totalLines = 0; let totalWords = 0; let totalChars = 0; @@ -21,7 +35,7 @@ let totalChars = 0; for (const filePath of filePaths) { const content = await fs.readFile(filePath, "utf-8"); - const lineCount = content.split("\n").length; + const lineCount = (content.match(/\n/g) || []).length; const wordCount = content.trim().split(/\s+/).length; const charCount = content.length; @@ -29,29 +43,13 @@ for (const filePath of filePaths) { totalWords += wordCount; totalChars += charCount; - let output = ""; - - if (options.l || options.w || options.c) { - if (options.l) output += `${lineCount} `; - if (options.w) output += `${wordCount} `; - if (options.c) output += `${charCount} `; - } else { - output += `${lineCount} ${wordCount} ${charCount} `; - } + const output = formatCounts(lineCount, wordCount, charCount, options); console.log(`${output}${filePath}`); } if (filePaths.length > 1) { - let totalOutput = ""; - - if (options.l || options.w || options.c) { - if (options.l) totalOutput += `${totalLines} `; - if (options.w) totalOutput += `${totalWords} `; - if (options.c) totalOutput += `${totalChars} `; - } else { - totalOutput += `${totalLines} ${totalWords} ${totalChars} `; - } + const totalOutput = formatCounts(totalLines, totalWords, totalChars, options); console.log(`${totalOutput}total`); }