diff --git a/implement-shell-tools/cat/cat.js b/implement-shell-tools/cat/cat.js new file mode 100644 index 000000000..9bb69a558 --- /dev/null +++ b/implement-shell-tools/cat/cat.js @@ -0,0 +1,43 @@ +const fs = require("fs"); + +const args = process.argv.slice(2); + +let mode = "normal"; +let files = []; + +if (args[0] === "-n") { + mode = "number"; + files = args.slice(1); +} else if (args[0] === "-b") { + mode = "numberNonEmpty"; + files = args.slice(1); +} else { + files = args; +} + +let lineNum = 1; + +for (const file of files) { + const content = fs.readFileSync(file, "utf8"); + + const lines = content.replace(/\n$/, "").split("\n"); + + if (mode === "normal") { + console.log(content); + continue; + } + + for (const line of lines) { + if (mode === "number") { + console.log(`${String(lineNum).padStart(6)} ${line}`); + lineNum++; + } else if (mode === "numberNonEmpty") { + if (line === "") { + console.log(""); + } else { + console.log(`${String(lineNum).padStart(6)} ${line}`); + lineNum++; + } + } + } +} diff --git a/implement-shell-tools/ls/ls.js b/implement-shell-tools/ls/ls.js new file mode 100644 index 000000000..dadc9b6ab --- /dev/null +++ b/implement-shell-tools/ls/ls.js @@ -0,0 +1,77 @@ +const fs = require("fs"); +const pathModule = require("path"); + +const args = process.argv.slice(2); + +let mode = "normal"; +let showHidden = false; +let paths = []; + +for (const arg of args) { + if (arg === "-1") { + mode = "onePerLine"; + } else if (arg === "-a") { + showHidden = true; + } else { + paths.push(arg); + } +} + +if (paths.length === 0) { + paths.push("."); +} + +function listDirectory(dir) { + let items = fs.readdirSync(dir); + + if (showHidden) { + items.unshift(".", ".."); + } else { + items = items.filter(item => !item.startsWith(".")); + } + + if (mode === "onePerLine") { + items.forEach(item => console.log(item)); + } else { + console.log(items.join(" ")); + } +} + +function expandWildcard(input) { + if (!input.includes("*")) { + return [input]; + } + const dir = pathModule.dirname(input); + const pattern = pathModule.basename(input); + const files = fs.readdirSync(dir); + + return files + .filter(file => { + if (pattern === "*") { + return showHidden || !file.startsWith("."); + } + + return file === pattern; + }) + .map(file => pathModule.join(dir, file)); +} + +for (const originalPath of paths) { + + const expandedPaths = expandWildcard(originalPath); + + for (const currentPath of expandedPaths) { + + const info = fs.statSync(currentPath); + + if (info.isDirectory()) { + listDirectory(currentPath); + } + + else if (info.isFile()) { + console.log(pathModule.basename(currentPath)); + } + + } + +} \ No newline at end of file diff --git a/implement-shell-tools/wc/wc.js b/implement-shell-tools/wc/wc.js new file mode 100644 index 000000000..398e1e6e4 --- /dev/null +++ b/implement-shell-tools/wc/wc.js @@ -0,0 +1,109 @@ +const fs = require("fs"); +const path = require("path"); + +const args = process.argv.slice(2); + +let countLines = false; +let countWords = false; +let countBytes = false; + +let files = []; + +for (const arg of args) { + if (arg === "-l") { + countLines = true; + } else if (arg === "-w") { + countWords = true; + } else if (arg === "-c") { + countBytes = true; + } else { + files.push(arg); + } +} + +function expandWildcard(filePath) { + if (!filePath.includes("*")) { + return [filePath]; + } + + const dir = path.dirname(filePath); + const files = fs.readdirSync(dir); + + return files.map(file => path.join(dir, file)); +} + +function getStats(filename) { + + const content = fs.readFileSync(filename, "utf8"); + + const lines = content.split("\n").length - 1; + + const words = content + .trim() + .split(/\s+/) + .filter(word => word.length > 0) + .length; + + const bytes = fs.statSync(filename).size; + + return { + lines, + words, + bytes + }; +} + +function printResult(stats, filename, showFilename = true) { + + let output = []; + + if (!countLines && !countWords && !countBytes) { + output.push(stats.lines); + output.push(stats.words); + output.push(stats.bytes); + } else { + if (countLines) { + output.push(stats.lines); + } + + if (countWords) { + output.push(stats.words); + } + + if (countBytes) { + output.push(stats.bytes); + } + } + + if (showFilename) { + output.push(filename); + } + + console.log(output.join(" ")); +} + +let allFiles = []; + +for (const file of files) { + allFiles.push(...expandWildcard(file)); +} + +let total = { + lines: 0, + words: 0, + bytes: 0 +}; + +for (const file of allFiles) { + + const stats = getStats(file); + + total.lines += stats.lines; + total.words += stats.words; + total.bytes += stats.bytes; + + printResult(stats, file); +} +if (allFiles.length > 1) { + printResult(total, "total"); +} \ No newline at end of file