Skip to content
Open
51 changes: 51 additions & 0 deletions implement-shell-tools/cat/cat.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import { readFile } from "node:fs/promises";
import process from "node:process";
import { parseArgs } from "node:util";

const { values, positionals: files } = parseArgs({
args: process.argv.slice(2),
options: {
number: {
type: "boolean",
short: "n",
},
numberNonBlank: {
type: "boolean",
short: "b",
},
},
allowPositionals: true,
});

const showLineNumbers = values.number ?? false;
const numberNonBlankLines = values.numberNonBlank ?? false;

let lineNumber = 1;

for (const file of files) {
try {
const content = await readFile(file, "utf-8");

const lines = content.split("\n");

if (numberNonBlankLines) {
for (const line of lines) {
if (line !== "") {
console.log(`${lineNumber} ${line}`);
lineNumber++;
} else {
console.log("");
}
}
} else if (showLineNumbers) {
for (const line of lines) {
console.log(`${lineNumber} ${line}`);
lineNumber++;
}
} else {
process.stdout.write(content);
}
} catch (err) {
console.error(err.message);
}
}
51 changes: 51 additions & 0 deletions implement-shell-tools/ls/ls.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import { readdir, stat } from "node:fs/promises";
import process from "node:process";

const argv = process.argv.slice(2);

let onePerLine = false;
let showAll = false;
const paths = [];

for (const arg of argv) {
if (arg === "-1") {
onePerLine = true;
} else if (arg === "-a") {
showAll = true;
} else {
paths.push(arg);
}
}

if (paths.length === 0) {
paths.push(".");
}

for (const path of paths) {
try {
const info = await stat(path);

if (info.isDirectory()) {
let files = await readdir(path);

if (!showAll) {
files = files.filter((file) => !file.startsWith("."));
}

if (onePerLine) {
for (const file of files) {
console.log(file);
}
} else {
for (const file of files) {
process.stdout.write(`${file} `);
}
process.stdout.write("\n");
}
} else {
console.log(path);
}
} catch (err) {
console.error(err.message);
}
}
85 changes: 85 additions & 0 deletions implement-shell-tools/wc/wc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
import { readFile } from "node:fs/promises";
import process from "node:process";
import { parseArgs } from "node:util";

const { values, positionals: files } = parseArgs({
args: process.argv.slice(2),

options: {
lines: {
type: "boolean",
short: "l",
},

words: {
type: "boolean",
short: "w",
},

bytes: {
type: "boolean",
short: "c",
},
},

allowPositionals: true,
});

const countLines = values.lines ?? false;
const countWords = values.words ?? false;
const countBytes = values.bytes ?? false;

function printCounts(lines, words, bytes, label) {
const parts = [];

if (countLines) {
parts.push(lines);
}

if (countWords) {
parts.push(words);
}

if (countBytes) {
parts.push(bytes);
}

if (!countLines && !countWords && !countBytes) {
parts.push(lines, words, bytes);
}

const output = parts.map((value) => String(value).padStart(8)).join("");

process.stdout.write(`${output} ${label}\n`);
}

let totalWords = 0;
let totalLines = 0;
let totalBytes = 0;

for (const file of files) {
try {
const content = await readFile(file, "utf-8");
const arrayOfLines = content.split("\n");
const arrayOfWords = content.trim().split(/\s+/)
const bytes = Buffer.byteLength(content, "utf-8");
const lines = arrayOfLines.length -1;
const words = arrayOfWords.length;
totalLines += lines;
totalBytes += bytes;
totalWords += words;
printCounts(lines, words, bytes, file);

} catch (err) {
console.error(err.message);
}
}

if (files.length > 1) {
printCounts(
totalLines,
totalWords,
totalBytes,
"total"
);
}
Loading