From a6701f16d40fec3da06fcbc1577a0382c87bb790 Mon Sep 17 00:00:00 2001 From: shaghayeghfar <146011477+shaghayeghfar@users.noreply.github.com> Date: Wed, 22 Jul 2026 13:00:59 +0100 Subject: [PATCH 1/3] implement-shell-tools are done --- implement-shell-tools/cat/cat.js | 48 ++++++++++++++++++++++ implement-shell-tools/ls/ls.js | 49 +++++++++++++++++++++++ implement-shell-tools/wc/wc.js | 68 ++++++++++++++++++++++++++++++++ 3 files changed, 165 insertions(+) create mode 100644 implement-shell-tools/cat/cat.js create mode 100644 implement-shell-tools/ls/ls.js create mode 100644 implement-shell-tools/wc/wc.js diff --git a/implement-shell-tools/cat/cat.js b/implement-shell-tools/cat/cat.js new file mode 100644 index 000000000..ffe23be65 --- /dev/null +++ b/implement-shell-tools/cat/cat.js @@ -0,0 +1,48 @@ +const fs = require("fs"); + +const args = process.argv.slice(2); + +let numberAllLines = false; +let numberNonBlankLines = false; +let startIndex = 0; +let lineNumber = 1; + +// Check for flags +if (args[0] === "-n") { + numberAllLines = true; + startIndex = 1; +} else if (args[0] === "-b") { + numberNonBlankLines = true; + startIndex = 1; +} + +// Read each file +for (let i = startIndex; i < args.length; i++) { + let fileName = args[i]; + + try { + let content = fs.readFileSync(fileName, "utf8"); + + let lines = content.split("\n"); + + for (let j = 0; j < lines.length; j++) { + let line = lines[j]; + + if (numberAllLines) { + console.log(lineNumber + " " + line); + lineNumber++; + } else if (numberNonBlankLines) { + if (line.trim() === "") { + console.log(line); + } else { + console.log(lineNumber + " " + line); + lineNumber++; + } + } else { + console.log(line); + } + } + } catch (error) { + console.log("Cannot read file: " + fileName); + } +} diff --git a/implement-shell-tools/ls/ls.js b/implement-shell-tools/ls/ls.js new file mode 100644 index 000000000..ff668fbbf --- /dev/null +++ b/implement-shell-tools/ls/ls.js @@ -0,0 +1,49 @@ +const fs = require("fs"); + +const args = process.argv.slice(2); + +let onePerLine = false; +let showHidden = false; +let path = "."; // Current directory by default + +// Check for flags +for (let i = 0; i < args.length; i++) { + if (args[i] === "-1") { + onePerLine = true; + } else if (args[i] === "-a") { + showHidden = true; + } else { + path = args[i]; + } +} + +try { + // Check if the path is a file + if (fs.statSync(path).isFile()) { + console.log(path); + } else { + let files = fs.readdirSync(path); + + // Print each file + for (let i = 0; i < files.length; i++) { + let file = files[i]; + + // Skip hidden files unless -a is used + if (!showHidden && file.startsWith(".")) { + continue; + } + + if (onePerLine) { + console.log(file); + } else { + process.stdout.write(file + " "); + } + } + + if (!onePerLine) { + console.log(); + } + } +} catch (error) { + console.log("Cannot access: " + path); +} diff --git a/implement-shell-tools/wc/wc.js b/implement-shell-tools/wc/wc.js new file mode 100644 index 000000000..1b27be980 --- /dev/null +++ b/implement-shell-tools/wc/wc.js @@ -0,0 +1,68 @@ +const fs = require("fs"); + +// Get arguments after "node wc.js" +const args = process.argv.slice(2); + +let countLines = false; +let countWords = false; +let countBytes = false; + +let files = []; + +// Read arguments +for (let arg of args) { + if (arg === "-l") { + countLines = true; + } else if (arg === "-w") { + countWords = true; + } else if (arg === "-c") { + countBytes = true; + } else { + files.push(arg); + } +} + +// If no flags are given, wc shows all three +if (!countLines && !countWords && !countBytes) { + countLines = true; + countWords = true; + countBytes = true; +} + +// Function to count one file +function countFile(fileName) { + const content = fs.readFileSync(fileName, "utf8"); + + let lines = content.split("\n").length - 1; + + let words = content + .trim() + .split(/\s+/) + .filter((word) => word.length > 0).length; + + let bytes = Buffer.byteLength(content); + + let result = ""; + + if (countLines) { + result += lines + " "; + } + + if (countWords) { + result += words + " "; + } + + if (countBytes) { + result += bytes + " "; + } + + result += fileName; + + console.log(result); +} + +// Run wc for every file + +for (let file of files) { + countFile(file); +} From f8562b3983b818f48e3ad97c2799b11044171356 Mon Sep 17 00:00:00 2001 From: shaghayeghfar <146011477+shaghayeghfar@users.noreply.github.com> Date: Fri, 24 Jul 2026 10:23:25 +0100 Subject: [PATCH 2/3] ls bugs were fixec --- implement-shell-tools/ls/ls.js | 62 ++++++++++++++++++++-------------- 1 file changed, 37 insertions(+), 25 deletions(-) diff --git a/implement-shell-tools/ls/ls.js b/implement-shell-tools/ls/ls.js index ff668fbbf..f60725956 100644 --- a/implement-shell-tools/ls/ls.js +++ b/implement-shell-tools/ls/ls.js @@ -4,7 +4,7 @@ const args = process.argv.slice(2); let onePerLine = false; let showHidden = false; -let path = "."; // Current directory by default +let paths = []; // Check for flags for (let i = 0; i < args.length; i++) { @@ -13,37 +13,49 @@ for (let i = 0; i < args.length; i++) { } else if (args[i] === "-a") { showHidden = true; } else { - path = args[i]; + paths.push(args[i]); } } -try { - // Check if the path is a file - if (fs.statSync(path).isFile()) { - console.log(path); - } else { - let files = fs.readdirSync(path); - - // Print each file - for (let i = 0; i < files.length; i++) { - let file = files[i]; +// Use current directory if no path is given +if (paths.length === 0) { + paths.push("."); +} - // Skip hidden files unless -a is used - if (!showHidden && file.startsWith(".")) { - continue; +for (let i = 0; i < paths.length; i++) { + let path = paths[i]; + + try { + // Check if the path is a file + if (fs.statSync(path).isFile()) { + console.log(path); + } else { + let files = fs.readdirSync(path); + + // Sort files like ls command + files.sort(); + + // Print each file + for (let j = 0; j < files.length; j++) { + let file = files[j]; + + // Skip hidden files unless -a is used + if (!showHidden && file.startsWith(".")) { + continue; + } + + if (onePerLine) { + console.log(file); + } else { + process.stdout.write(file + " "); + } } - if (onePerLine) { - console.log(file); - } else { - process.stdout.write(file + " "); + if (!onePerLine) { + console.log(); } } - - if (!onePerLine) { - console.log(); - } + } catch (error) { + console.log("Cannot access: " + path); } -} catch (error) { - console.log("Cannot access: " + path); } From 23467a8241507dd0a2f28feae45c0c2586be62a4 Mon Sep 17 00:00:00 2001 From: shaghayeghfar <146011477+shaghayeghfar@users.noreply.github.com> Date: Fri, 24 Jul 2026 17:16:19 +0100 Subject: [PATCH 3/3] changes were done --- implement-shell-tools/cat/cat.js | 21 ++++++---- implement-shell-tools/wc/wc.js | 69 ++++++++++++++++++++++++-------- 2 files changed, 66 insertions(+), 24 deletions(-) diff --git a/implement-shell-tools/cat/cat.js b/implement-shell-tools/cat/cat.js index ffe23be65..2ec18487d 100644 --- a/implement-shell-tools/cat/cat.js +++ b/implement-shell-tools/cat/cat.js @@ -8,12 +8,16 @@ let startIndex = 0; let lineNumber = 1; // Check for flags -if (args[0] === "-n") { - numberAllLines = true; - startIndex = 1; -} else if (args[0] === "-b") { - numberNonBlankLines = true; - startIndex = 1; +for (let i = 0; i < args.length; i++) { + if (args[i] === "-n") { + numberAllLines = true; + startIndex++; + } else if (args[i] === "-b") { + numberNonBlankLines = true; + startIndex++; + } else { + break; + } } // Read each file @@ -23,7 +27,10 @@ for (let i = startIndex; i < args.length; i++) { try { let content = fs.readFileSync(fileName, "utf8"); - let lines = content.split("\n"); + // Remove the extra empty line if the file ends with "\n" + let lines = content.endsWith("\n") + ? content.slice(0, -1).split("\n") + : content.split("\n"); for (let j = 0; j < lines.length; j++) { let line = lines[j]; diff --git a/implement-shell-tools/wc/wc.js b/implement-shell-tools/wc/wc.js index 1b27be980..1a59c238e 100644 --- a/implement-shell-tools/wc/wc.js +++ b/implement-shell-tools/wc/wc.js @@ -29,40 +29,75 @@ if (!countLines && !countWords && !countBytes) { countBytes = true; } +// Totals +let totalLines = 0; +let totalWords = 0; +let totalBytes = 0; +let filesCounted = 0; + // Function to count one file function countFile(fileName) { - const content = fs.readFileSync(fileName, "utf8"); + try { + const content = fs.readFileSync(fileName, "utf8"); + + let lines = content.split("\n").length - 1; + + let words = content + .trim() + .split(/\s+/) + .filter((word) => word.length > 0).length; + + let bytes = Buffer.byteLength(content); + + totalLines += lines; + totalWords += words; + totalBytes += bytes; + filesCounted++; + + let result = ""; - let lines = content.split("\n").length - 1; + if (countLines) { + result += lines + " "; + } - let words = content - .trim() - .split(/\s+/) - .filter((word) => word.length > 0).length; + if (countWords) { + result += words + " "; + } - let bytes = Buffer.byteLength(content); + if (countBytes) { + result += bytes + " "; + } + result += fileName; + + console.log(result); + } catch (error) { + console.log("Cannot read file: " + fileName); + } +} + +// Run wc for every file +for (let file of files) { + countFile(file); +} + +// Print totals if more than one file was counted +if (filesCounted > 1) { let result = ""; if (countLines) { - result += lines + " "; + result += totalLines + " "; } if (countWords) { - result += words + " "; + result += totalWords + " "; } if (countBytes) { - result += bytes + " "; + result += totalBytes + " "; } - result += fileName; + result += "total"; console.log(result); } - -// Run wc for every file - -for (let file of files) { - countFile(file); -}