diff --git a/implement-shell-tools/cat/cat.js b/implement-shell-tools/cat/cat.js new file mode 100644 index 000000000..0563a28fa --- /dev/null +++ b/implement-shell-tools/cat/cat.js @@ -0,0 +1,54 @@ +import process from "node:process"; +import { promises as fs } from "node:fs"; + +const args = process.argv.slice(2); + +let option = "none"; +const paths = []; + + +for (const arg of args) { + if (arg === "-n") { + option = "n"; + } else if (arg === "-b") { + option = "b"; + } else { + paths.push(arg); + } +} + +if (paths.length === 0) { + console.error("Expected at least one file path."); + process.exit(1); +} + +for (const path of paths) { + const content = await fs.readFile(path, "utf-8"); + + const lines = content.split("\n"); + + let lineNumber = 1; + + for (const line of lines) { + + if (option === "n") { + console.log(`${lineNumber} ${line}`); + lineNumber++; + } + + else if (option === "b") { + + if (line !== "") { + console.log(`${lineNumber} ${line}`); + lineNumber++; + } else { + console.log(""); + } + + } + + else { + console.log(line); + } + } +} \ No newline at end of file diff --git a/implement-shell-tools/ls/ls.js b/implement-shell-tools/ls/ls.js new file mode 100644 index 000000000..d7b1efe73 --- /dev/null +++ b/implement-shell-tools/ls/ls.js @@ -0,0 +1,28 @@ +import { program } from "commander"; +import { promises as fs } from "node:fs"; + +program + .name("ls") + .description("List directory contents") + .option("-a, --all", "show hidden files") + .option("-1, --one-per-line", "display one file per line") + .argument("[path]", "directory to list", "."); + +program.parse(); + +const options = program.opts(); +const path = program.args[0] || "."; + +const files = await fs.readdir(path); + +const filteredFiles = files.filter((file) => { + return options.all || !file.startsWith("."); +}); + +if (options.onePerLine) { + for (const file of filteredFiles) { + console.log(file); + } +} else { + console.log(filteredFiles.join(" ")); +} \ No newline at end of file diff --git a/implement-shell-tools/package-lock.json b/implement-shell-tools/package-lock.json new file mode 100644 index 000000000..0bdcfb87e --- /dev/null +++ b/implement-shell-tools/package-lock.json @@ -0,0 +1,21 @@ +{ + "name": "implement-shell-tools", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "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..c85f233e0 --- /dev/null +++ b/implement-shell-tools/package.json @@ -0,0 +1,17 @@ +{ + "dependencies": { + "commander": "^15.0.0" + }, + "name": "implement-shell-tools", + "version": "1.0.0", + "description": "Your task is to re-implement shell tools you have used.", + "main": "index.js", + "devDependencies": {}, + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "keywords": [], + "author": "", + "license": "ISC", + "type": "module" +} diff --git a/implement-shell-tools/wc/wc.js b/implement-shell-tools/wc/wc.js new file mode 100644 index 000000000..a57901653 --- /dev/null +++ b/implement-shell-tools/wc/wc.js @@ -0,0 +1,44 @@ +import process from "node:process"; +import { promises as fs } from "node:fs"; + +const args = process.argv.slice(2); + +let countLines = false; +let countWords = false; +let countChars = false; +const paths = []; + +// parse args +for (const arg of args) { + if (arg === "-l") countLines = true; + else if (arg === "-w") countWords = true; + else if (arg === "-c") countChars = true; + else paths.push(arg); +} + +if (paths.length === 0) { + console.error("Please provide at least one file"); + process.exit(1); +} + +for (const path of paths) { + const content = await fs.readFile(path, "utf-8"); + + const lines = content.split("\n").length; + const words = content.trim().split(/\s+/).length; + const chars = content.length; + + // if no flags → show all + if (!countLines && !countWords && !countChars) { + console.log(lines, words, chars, path); + continue; + } + + const output = []; + + if (countLines) output.push(lines); + if (countWords) output.push(words); + if (countChars) output.push(chars); + + console.log(...output, path); +} \ No newline at end of file