diff --git a/implement-shell-tools/cat/cat.js b/implement-shell-tools/cat/cat.js new file mode 100644 index 0000000..ec31edb --- /dev/null +++ b/implement-shell-tools/cat/cat.js @@ -0,0 +1,47 @@ +const { promises: fs } = require("fs"); +const process = require("process"); +const { program } = require("commander"); + +program + .name("cat") + .description("Implement a version of the cat program") + .option("-n, --number", "Number the output lines, starting at 1") + .option("-b, --number2", "Number the nonempty lines, starting at 1") + .argument("", "The file paths to process") + .parse(process.argv); + +let args = program.args; +//const nOption = program.opts().number; +//const bOption = program.opts().number2; +const { number: nOption, number2: bOption } = program.opts(); +let lineNumber = 1; +let nonEmptyLineNumber = 1; + +function printLinesWithOptions(lines) { + lines.forEach((line, index) => { + if (nOption) { + console.log(`${lineNumber++} ${line}`); + } else if (bOption && line.trim()) { + console.log(`${nonEmptyLineNumber++} ${line}`); + } else { + console.log(line); + } + }); +} + +async function readFileContent(path) { + try { + const content = await fs.readFile(path, { encoding: "utf-8" }); + const lines = content.split("\n"); + if(lines[lines.length - 1] === "") { + lines.pop(); + } + printLinesWithOptions(lines); + } catch (err) { + console.error(`Error reading file ${path}: ${err.message}`); + } +} + +args.forEach((arg) => { + readFileContent(arg); +}); diff --git a/implement-shell-tools/ls/ls.js b/implement-shell-tools/ls/ls.js new file mode 100644 index 0000000..c352e05 --- /dev/null +++ b/implement-shell-tools/ls/ls.js @@ -0,0 +1,37 @@ +const fs = require('fs'); +const { program } = require('commander'); + +program + .option('-a, --all', 'Show hidden files') + .option('-1', 'Show one file per line') + .argument('[dirPath]', 'Directory path', '.') + .parse(process.argv); + +const { all, '1': onePerLine } = program.opts(); +const dirPath = program.args[0] || '.'; + +if (typeof dirPath !== 'string') { + console.error('Error: Invalid directory path'); + process.exit(1); +} + +function listDirectoryContents(dirPath, showHidden = false, onePerLine = false) { + fs.readdir(dirPath, (err, files) => { + if (err) { + console.error(`Error reading directory: ${err.message}`); + return; + } + + if (!showHidden) { + files = files.filter(file => !file.startsWith('.')); + } + + if (onePerLine) { + files.forEach(file => console.log(file)); + } else { + console.log(files.join(' ')); + } + }); +} + +listDirectoryContents(dirPath, all, onePerLine); diff --git a/implement-shell-tools/wc/wc.js b/implement-shell-tools/wc/wc.js new file mode 100644 index 0000000..3661064 --- /dev/null +++ b/implement-shell-tools/wc/wc.js @@ -0,0 +1,71 @@ +const { promises: fs } = require('fs'); +const path = require('path'); +const { program } = require('commander'); + +program + .description('Count lines, words, and characters in the specified files') + .option('-l, --lines', 'Count the lines') + .option('-w, --words', 'Count the words') + .option('-c, --characters', 'Count the characters') + .parse(process.argv); + +const options = program.opts(); +const files = program.args; + +if (files.length === 0) { + console.error("Error: No files provided."); + process.exit(1); +} + +async function countFileStats(filePath, options) { + try { + const data = await fs.readFile(filePath, 'utf8'); + + const lines = data.split('\n').length; + const words = data.split(/\s+/).filter(Boolean).length; + const characters = data.length; + + const result = { lines, words, characters }; + const output = []; + if (options.lines) output.push(result.lines); + if (options.words) output.push(result.words); + if (options.characters) output.push(result.characters); + if (output.length === 0) output.push(result.lines, result.words, result.characters); + + return { file: filePath, output: output.join(' '), lines, words, characters }; + } catch (err) { + console.error(`Error reading file: ${filePath}`); + return null; + } +} + +async function processFiles() { + let totalLines = 0; + let totalWords = 0; + let totalCharacters = 0; + + for (const file of files) { + const filePath = path.resolve(file); + const result = await countFileStats(filePath, options); + + if (result) { + console.log(result.output, result.file); + totalLines += result.lines; + totalWords += result.words; + totalCharacters += result.characters; + } + } + + if (files.length > 1) { + const totals = []; + if (options.lines !== false) totals.push(totalLines); + if (options.words !== false) totals.push(totalWords); + if (options.characters !== false) totals.push(totalCharacters); + + if (totals.length > 0) { + console.log(totals.join(' ') + ' total'); + } + } +} + +processFiles();