diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 00000000..032202ac Binary files /dev/null and b/.DS_Store differ diff --git a/implement-shell-tools/.DS_Store b/implement-shell-tools/.DS_Store new file mode 100644 index 00000000..a684d2a2 Binary files /dev/null and b/implement-shell-tools/.DS_Store differ diff --git a/implement-shell-tools/cat/.DS_Store b/implement-shell-tools/cat/.DS_Store new file mode 100644 index 00000000..fb68cfb5 Binary files /dev/null and b/implement-shell-tools/cat/.DS_Store differ diff --git a/implement-shell-tools/cat/sample-files/cat.js b/implement-shell-tools/cat/sample-files/cat.js new file mode 100644 index 00000000..c586d631 --- /dev/null +++ b/implement-shell-tools/cat/sample-files/cat.js @@ -0,0 +1,43 @@ +import { program } from "commander"; +import { promises as fs } from "node:fs"; + + +program + .name("cat") + .description("Prints file content with optional line numbers") + .argument("", "file to read") + .option("-n, --number", "number all lines") + .option("-b, --number-nonblank", "number non-blank lines only") + .parse(); + +const options = program.opts(); +const filePath = program.args[0]; + +try { + const content = await fs.readFile(filePath, "utf-8"); + const lines = content.split("\n"); + + lines.forEach((line, index) => { + const lineNumber = index + 1; + if (options.number) { + + console.log(`${lineNumber.toString().padStart(4)} ${line}`); + } else if (options.numberNonblank) { + + if (line.trim() === "") { + console.log(" " + line); + } else { + console.log(`${lineNumber.toString().padStart(4)} ${line}`); + } + } else { + + console.log(line); + } + }); +} catch (err) { + console.error(`Error reading file "${filePath}":`, err.message); + process.exit(1); +} + + + diff --git a/implement-shell-tools/ls/ls.js b/implement-shell-tools/ls/ls.js new file mode 100644 index 00000000..54f0c69b --- /dev/null +++ b/implement-shell-tools/ls/ls.js @@ -0,0 +1,37 @@ +import {program} from "commander"; +import {promises as fs} from "node:fs"; + +program + .name ("ls") + .description("List the file directory") + .option("-1","List one file per line") + .option("-a","Include hidden file") + .argument("[dir]", "Directory to list",".") + .parse(); + + const options = program.opts(); +const dir = program.args[0] || "."; + +try { + const items = await fs.readdir(dir, { withFileTypes: true }); + + let fileNames = items.map(item => item.name); + + // Filter out hidden files unless -a + if (!options.a) { + fileNames = fileNames.filter(name => !name.startsWith(".")); + } + + // Print output + if (options["1"]) { + // One file per line + fileNames.forEach(name => console.log(name)); + } else { + // Default: space-separated (like regular `ls`) + console.log(fileNames.join(" ")); + } +} catch (err) { + console.error(`Error reading directory "${dir}":`, err.message); + process.exit(1); +} + diff --git a/implement-shell-tools/wc/wc.js b/implement-shell-tools/wc/wc.js new file mode 100644 index 00000000..2685678f --- /dev/null +++ b/implement-shell-tools/wc/wc.js @@ -0,0 +1,38 @@ +import { program } from "commander"; +import { promises as fs } from "node:fs"; + +program + .name("wc") + .description("Custom wc CLI - count lines, words, bytes") + .argument("", "File to process") + .option("-l", "Print the number of lines") + .option("-w", "Print the number of words") + .option("-c", "Print the number of bytes") + .parse(); + +const options = program.opts(); +const filePath = program.args[0]; + +try { + const data = await fs.readFile(filePath,"utf-8"); + + + + const lineCount = data.split("\n").length; + const wordCount = data.trim().split(/\s+/).length; + const byteCount = data.length; + + const showAll = !options.l && !options.w && !options.c; + + + const output = []; + if (options.l || showAll) output.push(lineCount.toString().padStart(8)); + if (options.w || showAll) output.push(wordCount.toString().padStart(8)); + if (options.c || showAll) output.push(byteCount.toString().padStart(8)); + output.push(filePath); + + console.log(output.join(" ")); +} catch (err) { + console.error(`Error reading file "${filePath}":`, err.message); + process.exit(1); +} \ No newline at end of file diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 00000000..72b93ad7 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,21 @@ +{ + "name": "Module-Tools", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "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/package.json b/package.json new file mode 100644 index 00000000..ab8c9a34 --- /dev/null +++ b/package.json @@ -0,0 +1,5 @@ +{ + "dependencies": { + "commander": "^14.0.0" + } +}