Skip to content

Commit d6c3aaa

Browse files
feat: implement custom myCat command with wildcard support and line numbering
1 parent 407b010 commit d6c3aaa

File tree

1 file changed

+79
-0
lines changed
  • implement-shell-tools/cat/sample-files

1 file changed

+79
-0
lines changed
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
#!/usr/bin/env node
2+
const { program } = require("commander");
3+
const fs = require("fs");
4+
const path = require("path");
5+
6+
7+
8+
function expandWildcard(pattern) {
9+
const dir = path.dirname(pattern);
10+
const base = path.basename(pattern);
11+
12+
if (!base.includes("*")) return [pattern];
13+
14+
let files;
15+
try {
16+
files = fs.readdirSync(dir);
17+
} catch (e) {
18+
console.error(`cat: ${pattern}: No such directory`);
19+
return [];
20+
}
21+
22+
const regex = new RegExp("^" + base.replace(/\*/g, ".*") + "$");
23+
24+
return files
25+
.filter((f) => regex.test(f))
26+
.map((f) => path.join(dir, f));
27+
}
28+
29+
function printFile(filename, options) {
30+
let text;
31+
try {
32+
text = fs.readFileSync(filename, "utf-8");
33+
} catch {
34+
console.error(`cat: ${filename}: No such file`);
35+
return;
36+
}
37+
38+
const lines = text.split("\n");
39+
if (lines[lines.length - 1] === "") {
40+
lines.pop();
41+
}
42+
let counter = 1;
43+
44+
lines.forEach((line) => {
45+
if (options.numberAll) {
46+
const paddingSize = 6;
47+
console.log(`${String(counter).padStart(paddingSize)} ${line}`);
48+
counter++;
49+
} else if (options.numberNonempty) {
50+
if (line.trim() === "") {
51+
console.log("");
52+
} else {
53+
console.log(`${String(counter).padStart(paddingSize)} ${line}`);
54+
counter++;
55+
}
56+
} else {
57+
console.log(line);
58+
}
59+
});
60+
}
61+
62+
program
63+
.name("mycat")
64+
.description("A custom implementation of the cat command")
65+
.argument("<files...>", "files or wildcard patterns")
66+
.option("-n, --number-all", "number all lines")
67+
.option("-b, --number-nonempty", "number non-empty lines")
68+
.action((patterns, options) => {
69+
let allFiles = [];
70+
71+
patterns.forEach((p) => {
72+
allFiles = allFiles.concat(expandWildcard(p));
73+
});
74+
75+
allFiles.forEach((file) => printFile(file, options));
76+
});
77+
78+
program.parse();
79+

0 commit comments

Comments
 (0)