diff --git a/implement-shell-tools/cat/README.md b/implement-shell-tools/cat/README.md index 7284a5e67..71a08ca9b 100644 --- a/implement-shell-tools/cat/README.md +++ b/implement-shell-tools/cat/README.md @@ -6,11 +6,11 @@ Your task is to implement your own version of `cat`. It must act the same as `cat` would, if run from the directory containing this README.md file, for the following command lines: -* `cat sample-files/1.txt` -* `cat -n sample-files/1.txt` -* `cat sample-files/*.txt` -* `cat -n sample-files/*.txt` -* `cat -b sample-files/3.txt` +- `cat sample-files/1.txt` +- `cat -n sample-files/1.txt` +- `cat sample-files/*.txt` +- `cat -n sample-files/*.txt` +- `cat -b sample-files/3.txt` Matching any additional behaviours or flags are optional stretch goals. diff --git a/implement-shell-tools/cat/cat.js b/implement-shell-tools/cat/cat.js new file mode 100644 index 000000000..5961a6c39 --- /dev/null +++ b/implement-shell-tools/cat/cat.js @@ -0,0 +1,47 @@ +const fs = require("fs"); + +const args = process.argv.slice(2); + +let flag = ""; +let filePaths = []; + +if (args[0] && args[0].startsWith("-")) { + flag = args[0]; + filePaths = args.slice(1); +} else { + filePaths = args; +} + +// Read all files into one string +let content = filePaths.map((file) => fs.readFileSync(file, "utf-8")).join(""); + +// Split into lines +let lines = content.split(/\r?\n/); + +// Remove the last empty line if the file ends with a newline +if (lines[lines.length - 1] === "") { + lines.pop(); +} + +// Handle flag ==> -n adding number to the line; +if (flag === "-n") { + lines = lines.map((line, index) => { + return `${index + 1} ${line}`; + }); +} + +// Handle flag ==> -b avoids adding number to empty line +if (flag === "-b") { + let lineNumber = 1; + + lines = lines.map((line) => { + if (line.trim() === "") { + return line; + } + + return `${lineNumber++} ${line}`; + }); +} + +process.stdout.write(lines.join("\n")); + diff --git a/implement-shell-tools/ls/ls.js b/implement-shell-tools/ls/ls.js new file mode 100644 index 000000000..eda1e0e14 --- /dev/null +++ b/implement-shell-tools/ls/ls.js @@ -0,0 +1,40 @@ +const fs = require("fs"); + +const args = process.argv.slice(2); + +let flags = []; +let paths = []; + +// Check arguments: separate flags and paths +args.forEach((arg) => { + if (arg.startsWith("-")) { + flags.push(arg); + } else { + paths.push(arg); + } +}); + +// If no path is provided, use the current directory +if (paths.length === 0) { + paths = ["."]; +} + +paths.forEach((path) => { + if (fs.statSync(path).isFile()) { + console.log(path); + } else { + let contents = fs.readdirSync(path); + + // Hide hidden files unless -a exists + if (!flags.includes("-a")) { + contents = contents.filter((file) => !file.startsWith(".")); + } + + // Check -1 flag + if (flags.includes("-1")) { + console.log(contents.join("\n")); + } else { + console.log(contents.join(" ")); + } + } +}); diff --git a/implement-shell-tools/wc/wc.js b/implement-shell-tools/wc/wc.js new file mode 100644 index 000000000..7afd91897 --- /dev/null +++ b/implement-shell-tools/wc/wc.js @@ -0,0 +1,73 @@ +// Power shell commands with Js codes + +const fs = require("fs"); +const args = process.argv.slice(2); + +let flags = []; +let paths = []; + +// Check arguments: separate flags and paths +args.forEach((arg) => { + if (arg.startsWith("-")) { + flags.push(arg); + } else { + paths.push(arg); + } +}); + +let totalLines = 0; +let totalWords = 0; +let totalCharacters = 0; + +paths.forEach((file) => { + const content = fs.readFileSync(file, "utf-8"); + + const lines = content.split("\n").length - 1; + const words = content.trim().split(/\s+/).length; + const chars = content.length; + + if (flags.length === 0) { + console.log(lines, words, chars, file); + } else { + let output = []; + + if (flags.includes("-l")) { + output.push(lines); + } + + if (flags.includes("-w")) { + output.push(words); + } + + if (flags.includes("-c")) { + output.push(chars); + } + + console.log(...output, file); + } + + totalLines += lines; + totalWords += words; + totalCharacters += chars; +}); +if (paths.length > 1) { + let totalOutput = []; + + if (flags.length === 0) { + totalOutput.push(totalLines, totalWords, totalCharacters); + } else { + if (flags.includes("-l")) { + totalOutput.push(totalLines); + } + + if (flags.includes("-w")) { + totalOutput.push(totalWords); + } + + if (flags.includes("-c")) { + totalOutput.push(totalCharacters); + } + } + + console.log(...totalOutput, "total"); +}