Skip to content

Commit b964c6a

Browse files
committed
add wc tool with line, word, and byte counts in NodeJS
1 parent b1fbd45 commit b964c6a

File tree

1 file changed

+87
-0
lines changed
  • implement-shell-tools/wc

1 file changed

+87
-0
lines changed

implement-shell-tools/wc/wc.js

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
#!/usr/bin/env node
2+
3+
const fs = require("fs");
4+
const path = require("path");
5+
6+
// -------- argument parsing --------
7+
const args = process.argv.slice(2);
8+
9+
let countLines = false;
10+
let countWords = false;
11+
let countBytes = false;
12+
let files = [];
13+
14+
// flags can appear in any order
15+
for (const arg of args) {
16+
if (arg === "-l") countLines = true;
17+
else if (arg === "-w") countWords = true;
18+
else if (arg === "-c") countBytes = true;
19+
else files.push(arg);
20+
}
21+
22+
if (files.length === 0) {
23+
console.error("Usage: wc [-l] [-w] [-c] <file> [file...]");
24+
process.exit(1);
25+
}
26+
27+
// If no flags → behave like plain `wc`
28+
if (!countLines && !countWords && !countBytes) {
29+
countLines = true;
30+
countWords = true;
31+
countBytes = true;
32+
}
33+
34+
// -------- helpers --------
35+
function countFile(filePath) {
36+
let content;
37+
let buffer;
38+
39+
try {
40+
buffer = fs.readFileSync(filePath);
41+
content = buffer.toString("utf8");
42+
} catch (err) {
43+
console.error(`wc.js: ${filePath}: ${err.message}`);
44+
return null;
45+
}
46+
47+
const lines = content.split("\n").length - 1;
48+
const words = content.trim() === ""
49+
? 0
50+
: content.trim().split(/\s+/).length;
51+
const bytes = buffer.length;
52+
53+
return { lines, words, bytes };
54+
}
55+
56+
function formatOutput(counts, fileName) {
57+
const parts = [];
58+
59+
if (countLines) parts.push(counts.lines.toString().padStart(7, " "));
60+
if (countWords) parts.push(counts.words.toString().padStart(7, " "));
61+
if (countBytes) parts.push(counts.bytes.toString().padStart(7, " "));
62+
63+
parts.push(" " + fileName);
64+
return parts.join("");
65+
}
66+
67+
// -------- main --------
68+
let total = { lines: 0, words: 0, bytes: 0 };
69+
let validFileCount = 0;
70+
71+
for (const file of files) {
72+
const counts = countFile(file);
73+
if (!counts) continue;
74+
75+
validFileCount++;
76+
77+
total.lines += counts.lines;
78+
total.words += counts.words;
79+
total.bytes += counts.bytes;
80+
81+
process.stdout.write(formatOutput(counts, file) + "\n");
82+
}
83+
84+
// Print total if multiple files
85+
if (validFileCount > 1) {
86+
process.stdout.write(formatOutput(total, "total") + "\n");
87+
}

0 commit comments

Comments
 (0)