From 05f80d4c6dd68bf7811a5062fea00c6a32da356c Mon Sep 17 00:00:00 2001 From: Abubakar-Meigag <113248042+Abubakar-Meigag@users.noreply.github.com> Date: Fri, 17 Apr 2026 15:34:05 +0100 Subject: [PATCH] London | 26-SDC-Mar | Beko | Sprint 3 | Implement Shell Tools --- implement-shell-tools/cat/catFile.mjs | 44 +++++++++++++++++++++ implement-shell-tools/ls/lsFile.mjs | 19 +++++++++ implement-shell-tools/wc/wcFile.mjs | 55 +++++++++++++++++++++++++++ 3 files changed, 118 insertions(+) create mode 100644 implement-shell-tools/cat/catFile.mjs create mode 100644 implement-shell-tools/ls/lsFile.mjs create mode 100644 implement-shell-tools/wc/wcFile.mjs diff --git a/implement-shell-tools/cat/catFile.mjs b/implement-shell-tools/cat/catFile.mjs new file mode 100644 index 000000000..158d3e60a --- /dev/null +++ b/implement-shell-tools/cat/catFile.mjs @@ -0,0 +1,44 @@ +import process from "node:process"; +import { promises as fs } from "node:fs"; + +const argv = process.argv.slice(2); + +const dash = argv.filter(arg => arg.startsWith('-')); +const filePaths = argv.filter(arg => !arg.startsWith('-')); + +const showLineNumbers = dash.includes('-n'); +const showNonBlank = dash.includes('-b'); + +let lineCounter = 1; + +for (const filePath of filePaths) { + let content; + try { + content = await fs.readFile(filePath, 'utf8'); + } catch { + console.error(`cat: ${filePath}: No file or directory exists`); + process.exit(1); + } + + const lines = content.split('\n'); + + if (lines[lines.length - 1] === '') lines.pop(); + + for (const line of lines) { + const isBlank = line.trim() === ''; + + if (showNonBlank) { + if (isBlank) { + console.log(''); + } else { + console.log(`${String(lineCounter).padStart(6)}\t${line}`); + lineCounter++; + } + } else if (showLineNumbers) { + console.log(`${String(lineCounter).padStart(6)}\t${line}`); + lineCounter++; + } else { + console.log(line); + } + } +} diff --git a/implement-shell-tools/ls/lsFile.mjs b/implement-shell-tools/ls/lsFile.mjs new file mode 100644 index 000000000..d4a6427d9 --- /dev/null +++ b/implement-shell-tools/ls/lsFile.mjs @@ -0,0 +1,19 @@ +import process from "node:process"; +import { promises as fs } from "node:fs"; + +const argv = process.argv.slice(2); + +const dash = argv.filter(arg => arg.startsWith('-')); +const paths = argv.filter(arg => !arg.startsWith('-')); + +const showAll = dash.includes('-a'); + +const targetDir = paths[0] ?? '.'; + +const entries = await fs.readdir(targetDir); + +const result = showAll ? ['.', '..', ...entries] : entries.filter(e => !e.startsWith('.')); + +for (const entry of result) { + console.log(entry); +} diff --git a/implement-shell-tools/wc/wcFile.mjs b/implement-shell-tools/wc/wcFile.mjs new file mode 100644 index 000000000..7e06b00e7 --- /dev/null +++ b/implement-shell-tools/wc/wcFile.mjs @@ -0,0 +1,55 @@ +import process from "node:process"; +import { promises as fs } from "node:fs"; + +const argv = process.argv.slice(2); + +const dash = argv.filter(arg => arg.startsWith('-')); +const filePaths = argv.filter(arg => !arg.startsWith('-')); + +const forLines = dash.includes('-l'); +const forWords = dash.includes('-w'); +const forBytes = dash.includes('-c'); + +let totalLines = 0; +let totalWords = 0; +let totalBytes = 0; + +for (const filePath of filePaths) { + let content; + try { + content = await fs.readFile(filePath, 'utf8'); + } catch { + console.error(`wc: ${filePath}: No file or directory exists`); + process.exit(1); + } + + const lines = content.split('\n').length - 1; + const words = content.trim() === '' ? 0 : content.trim().split(/\s+/).length; + const bytes = Buffer.byteLength(content, 'utf8'); + + totalLines += lines; + totalWords += words; + totalBytes += bytes; + + if (forLines) { + console.log(`${String(lines).padStart(8)} ${filePath}`); + } else if (forWords) { + console.log(`${String(words).padStart(8)} ${filePath}`); + } else if (forBytes) { + console.log(`${String(bytes).padStart(8)} ${filePath}`); + } else { + console.log(`${String(lines).padStart(8)} ${String(words).padStart(8)} ${String(bytes).padStart(8)} ${filePath}`); + } +} + +if (filePaths.length > 1) { + if (forLines) { + console.log(`${String(totalLines).padStart(8)} total`); + } else if (forWords) { + console.log(`${String(totalWords).padStart(8)} total`); + } else if (forBytes) { + console.log(`${String(totalBytes).padStart(8)} total`); + } else { + console.log(`${String(totalLines).padStart(8)} ${String(totalWords).padStart(8)} ${String(totalBytes).padStart(8)} total`); + } +}