From 69df5ac32a0d635d97e2609702ed47b49ddcf051 Mon Sep 17 00:00:00 2001 From: ZabihollahNamazi Date: Wed, 25 Mar 2026 12:55:08 +0000 Subject: [PATCH 1/5] cat complete --- implement-shell-tools/cat/cat.js | 45 ++++++++++++++++++++++++++++++++ 1 file changed, 45 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 000000000..bc5c7168d --- /dev/null +++ b/implement-shell-tools/cat/cat.js @@ -0,0 +1,45 @@ +import { promises as fs } from "node:fs"; + +// get all command line arguments after "node cat.js" - like -n or -b +const args = process.argv.slice(2); + +// put them in variables +const showAllNumbers = args.includes("-n"); +const showNonEmptyNumbers = args.includes("-b"); + +// getting the paths of files +const paths = args.filter(arg => arg !== "-n" && arg !== "-b"); + +// loop over each file +for (const path of paths) { + try { + // read file as text + const content = await fs.readFile(path, "utf-8"); + + // split them into lines + const lines = content.split("\n"); + + let lineNumber = 1; // tracks line numbers for -b and -n + + lines.forEach((line) => { + if (showNonEmptyNumbers) { + // -b: number only non-empty lines + if (line.trim() !== "") { + console.log(`${lineNumber} ${line}`); + lineNumber++; + } else { + console.log(line); // shows empty line with no number + } + } else if (showAllNumbers) { + // -n: number all lines + console.log(`${lineNumber} ${line}`); + lineNumber++; + } else { + // no flags: just print line + console.log(line); + } + }); + } catch (err) { + console.error(`Error reading file "${path}": ${err.message}`); + } +} \ No newline at end of file From 2bf3b2abfc5acfa6f81b9411980b02e5a2934529 Mon Sep 17 00:00:00 2001 From: ZabihollahNamazi Date: Wed, 25 Mar 2026 14:07:58 +0000 Subject: [PATCH 2/5] ls done - "-1 for all files including hiddens and -a does not show hidden files --- implement-shell-tools/ls/ls.js | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 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 000000000..e75a8d992 --- /dev/null +++ b/implement-shell-tools/ls/ls.js @@ -0,0 +1,29 @@ +import { promises as fs } from "node:fs"; + +//getting all commands +const args = process.argv.slice(2); + +const showOnePerLine = args.includes("-1"); +const showAllFilesWithoutHidden = args.includes("-a"); + +//current path +const path = args.find(arg => !arg.startsWith("-")) || "."; +// if we do console.log("path=> ",path," args=> " ,args); it will give us this =>: path=> sample-files args=> [ '-1', '-a', 'sample-files' ] + +const direc = await fs.readdir(path) +// if the path is console.log(direc) gives us =>: [ '.hidden.txt', '1.txt', '2.txt', '3.txt', 'dir' ] + +if(showOnePerLine && showAllFilesWithoutHidden){ + const visibleFiles = direc.filter(element => !element.startsWith(".")); // filtering hidden files which starts with "." + visibleFiles.forEach(element => { + console.log(element) + }); +} +else if(showOnePerLine ){ // shows all file including .hidden files + direc.forEach(element => { + console.log(element) + }) +} + + + From 9ee1b4039c5f510c23f6d249b4b61f568b69c97a Mon Sep 17 00:00:00 2001 From: ZabihollahNamazi Date: Wed, 25 Mar 2026 14:12:19 +0000 Subject: [PATCH 3/5] update ls --- "-a to show hidden files too" "-1 for normal files" --- implement-shell-tools/ls/ls.js | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/implement-shell-tools/ls/ls.js b/implement-shell-tools/ls/ls.js index e75a8d992..3e042589f 100644 --- a/implement-shell-tools/ls/ls.js +++ b/implement-shell-tools/ls/ls.js @@ -4,7 +4,7 @@ import { promises as fs } from "node:fs"; const args = process.argv.slice(2); const showOnePerLine = args.includes("-1"); -const showAllFilesWithoutHidden = args.includes("-a"); +const showAllFilesWithHidden = args.includes("-a"); //current path const path = args.find(arg => !arg.startsWith("-")) || "."; @@ -13,17 +13,16 @@ const path = args.find(arg => !arg.startsWith("-")) || "."; const direc = await fs.readdir(path) // if the path is console.log(direc) gives us =>: [ '.hidden.txt', '1.txt', '2.txt', '3.txt', 'dir' ] -if(showOnePerLine && showAllFilesWithoutHidden){ +if(showOnePerLine && showAllFilesWithHidden){ + direc.forEach(element => { + console.log(element) + }) +} +else if(showOnePerLine){ const visibleFiles = direc.filter(element => !element.startsWith(".")); // filtering hidden files which starts with "." visibleFiles.forEach(element => { console.log(element) }); } -else if(showOnePerLine ){ // shows all file including .hidden files - direc.forEach(element => { - console.log(element) - }) -} - From d1a86b0ae24e8fb810d2636cd12b255f079fa5e2 Mon Sep 17 00:00:00 2001 From: ZabihollahNamazi Date: Wed, 25 Mar 2026 15:28:25 +0000 Subject: [PATCH 4/5] wc is done but the readme file does not syas if we need to do it with multiple flags --- implement-shell-tools/wc/README.md | 2 +- implement-shell-tools/wc/wc.js | 60 ++++++++++++++++++++++++++++++ 2 files changed, 61 insertions(+), 1 deletion(-) create mode 100644 implement-shell-tools/wc/wc.js diff --git a/implement-shell-tools/wc/README.md b/implement-shell-tools/wc/README.md index bd76b655a..98c2494d7 100644 --- a/implement-shell-tools/wc/README.md +++ b/implement-shell-tools/wc/README.md @@ -14,4 +14,4 @@ It must act the same as `wc` would, if run from the directory containing this RE Matching any additional behaviours or flags are optional stretch goals. -We recommend you start off supporting no flags for one file, then add support for multiple files, then add support for the flags. +We recommend you start off supporting no flags for one file, then add support for multiple files, then add support for the flags \ No newline at end of file diff --git a/implement-shell-tools/wc/wc.js b/implement-shell-tools/wc/wc.js new file mode 100644 index 000000000..2d747f06c --- /dev/null +++ b/implement-shell-tools/wc/wc.js @@ -0,0 +1,60 @@ +import { promises as fs } from "node:fs"; + +const args = process.argv.slice(2); +console.log(args) + +const showLines = args.includes("-l"); +const showWords = args.includes("-w"); +const showChars = args.includes("-c"); +const paths = args.filter(arg => !arg.startsWith("-")) || "."; +console.log(paths) + +// const direct = await fs.readdir(path); + +// console.log(direct); +let totalLines = 0; +let totalWords = 0; +let totalchars = 0; + +if(showLines){ + for (const path of paths){ + const content = await fs.readFile(path, "utf-8"); + const lines = content.split("\n").length; + + totalLines += lines; + } + console.log("line: ", totalLines); +} +else if(showWords){ + for (const path of paths){ + const content = await fs.readFile(path, "utf-8"); + const words = content.split(/\s+/).filter(Boolean).length; + + totalWords += words; + } + console.log("words: ", totalWords); +} +else if(showChars){ + for (const path of paths){ + const content = await fs.readFile(path, "utf-8"); + const char = content.length; + + totalchars += char; + } + console.log("chars", totalchars) +} +else{ + for (const path of paths){ + const content = await fs.readFile(path, "utf-8"); + const lines = content.split("\n").length; + const words = content.split(/\s+/).filter(Boolean).length; + const char = content.length; + + totalLines += lines; + totalWords += words; + totalchars += char; + } +console.log("lines: ", totalLines, " words", totalWords, " char:", totalchars) +} + + From 77765dc8a11ea87695862c42c9ffaeeeef47c457 Mon Sep 17 00:00:00 2001 From: ZabihollahNamazi Date: Sun, 31 May 2026 00:35:58 +0100 Subject: [PATCH 5/5] update --- implement-shell-tools/cat/cat.js | 13 +++--- implement-shell-tools/ls/ls.js | 35 +++++++++++----- implement-shell-tools/wc/wc.js | 71 +++++++++++++++----------------- 3 files changed, 65 insertions(+), 54 deletions(-) diff --git a/implement-shell-tools/cat/cat.js b/implement-shell-tools/cat/cat.js index bc5c7168d..e2f05ea15 100644 --- a/implement-shell-tools/cat/cat.js +++ b/implement-shell-tools/cat/cat.js @@ -10,6 +10,9 @@ const showNonEmptyNumbers = args.includes("-b"); // getting the paths of files const paths = args.filter(arg => arg !== "-n" && arg !== "-b"); +// helper: mimic real cat line number formatting +const padLineNumber = (num) => String(num).padStart(6, " "); + // loop over each file for (const path of paths) { try { @@ -21,24 +24,24 @@ for (const path of paths) { let lineNumber = 1; // tracks line numbers for -b and -n - lines.forEach((line) => { + for (const line of lines) { if (showNonEmptyNumbers) { // -b: number only non-empty lines - if (line.trim() !== "") { - console.log(`${lineNumber} ${line}`); + if (line !== "") { + console.log(`${padLineNumber(lineNumber)} ${line}`); lineNumber++; } else { console.log(line); // shows empty line with no number } } else if (showAllNumbers) { // -n: number all lines - console.log(`${lineNumber} ${line}`); + console.log(`${padLineNumber(lineNumber)} ${line}`); lineNumber++; } else { // no flags: just print line console.log(line); } - }); + } } catch (err) { console.error(`Error reading file "${path}": ${err.message}`); } diff --git a/implement-shell-tools/ls/ls.js b/implement-shell-tools/ls/ls.js index 3e042589f..e4978f897 100644 --- a/implement-shell-tools/ls/ls.js +++ b/implement-shell-tools/ls/ls.js @@ -10,19 +10,32 @@ const showAllFilesWithHidden = args.includes("-a"); const path = args.find(arg => !arg.startsWith("-")) || "."; // if we do console.log("path=> ",path," args=> " ,args); it will give us this =>: path=> sample-files args=> [ '-1', '-a', 'sample-files' ] -const direc = await fs.readdir(path) -// if the path is console.log(direc) gives us =>: [ '.hidden.txt', '1.txt', '2.txt', '3.txt', 'dir' ] +try { + const direc = await fs.readdir(path); -if(showOnePerLine && showAllFilesWithHidden){ - direc.forEach(element => { - console.log(element) - }) -} -else if(showOnePerLine){ - const visibleFiles = direc.filter(element => !element.startsWith(".")); // filtering hidden files which starts with "." - visibleFiles.forEach(element => { - console.log(element) + // handle hidden files (-a flag controls this) + let files = direc; + + if (!showAllFilesWithHidden) { + files = files.filter(file => !file.startsWith(".")); + } + + // one file per line + if (showOnePerLine) { + files.forEach(file => { + console.log(file); }); + } + + // default behavior: also one per line (simple version of ls) + else { + files.forEach(file => { + console.log(file); + }); + } + +} catch (err) { + console.error(`Error reading directory "${path}": ${err.message}`); } diff --git a/implement-shell-tools/wc/wc.js b/implement-shell-tools/wc/wc.js index 2d747f06c..dfd403507 100644 --- a/implement-shell-tools/wc/wc.js +++ b/implement-shell-tools/wc/wc.js @@ -1,60 +1,55 @@ import { promises as fs } from "node:fs"; const args = process.argv.slice(2); -console.log(args) const showLines = args.includes("-l"); const showWords = args.includes("-w"); const showChars = args.includes("-c"); -const paths = args.filter(arg => !arg.startsWith("-")) || "."; -console.log(paths) +let paths = args.filter(arg => !arg.startsWith("-")); +if (paths.length === 0) paths = ["."]; -// const direct = await fs.readdir(path); +// helper for formatting like real wc +const pad = (n) => String(n).padStart(8, " "); -// console.log(direct); let totalLines = 0; let totalWords = 0; -let totalchars = 0; +let totalChars = 0; -if(showLines){ - for (const path of paths){ - const content = await fs.readFile(path, "utf-8"); - const lines = content.split("\n").length; +for (const path of paths) { + try { + const content = await fs.readFile(path, "utf-8"); - totalLines += lines; + const lines = content.split("\n").length; + const words = content.split(/\s+/).filter(Boolean).length; + const chars = content.length; + + totalLines += lines; + totalWords += words; + totalChars += chars; + + } catch (err) { + console.error(`Error reading file "${path}": ${err.message}`); } - console.log("line: ", totalLines); + +} +if (showLines) { + console.log("lines:", totalLines); } -else if(showWords){ - for (const path of paths){ - const content = await fs.readFile(path, "utf-8"); - const words = content.split(/\s+/).filter(Boolean).length; - totalWords += words; - } - console.log("words: ", totalWords); +if (showWords) { + console.log("words:", totalWords); } -else if(showChars){ - for (const path of paths){ - const content = await fs.readFile(path, "utf-8"); - const char = content.length; - totalchars += char; - } - console.log("chars", totalchars) +if (showChars) { + console.log("chars:", totalChars); } -else{ - for (const path of paths){ - const content = await fs.readFile(path, "utf-8"); - const lines = content.split("\n").length; - const words = content.split(/\s+/).filter(Boolean).length; - const char = content.length; - - totalLines += lines; - totalWords += words; - totalchars += char; - } -console.log("lines: ", totalLines, " words", totalWords, " char:", totalchars) + + +// default output when no flags +if (!showLines && !showWords && !showChars) { + console.log( + `${pad(totalLines)}\t${pad(totalWords)}\t${pad(totalChars)}\ttotal` + ); }