Skip to content

Commit e6fccc8

Browse files
committed
feat(ls): add basic ls CLI with -1 and -a support
- Add ls/ls.js: reads a directory, supports -1 (one-per-line) and -a (include dotfiles) - Use commander for CLI flags, fs.promises.readdir for reading directories - Add error handling and set non-zero exit code on failure - docs(ls): normalize README bullets so example commands render correctly
1 parent 7693032 commit e6fccc8

2 files changed

Lines changed: 69 additions & 3 deletions

File tree

implement-shell-tools/ls/README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@ Your task is to implement your own version of `ls`.
66

77
It must act the same as `ls` would, if run from the directory containing this README.md file, for the following command lines:
88

9-
* `ls -1`
10-
* `ls -1 sample-files`
11-
* `ls -1 -a sample-files`
9+
- `ls -1`
10+
- `ls -1 sample-files`
11+
- `ls -1 -a sample-files`
1212

1313
Matching any additional behaviours or flags are optional stretch goals.
1414

implement-shell-tools/ls/ls.js

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
import process from "node:process";
2+
import { promises as fs } from "node:fs";
3+
import { program } from "commander";
4+
5+
program
6+
.option("-1, --one-per-line", "list one file per line")
7+
.option("-a, --all", "do not ignore entries starting with .")
8+
.parse();
9+
10+
const cliOptions = program.opts();
11+
const cliArguments = program.args;
12+
13+
async function runLsCommand() {
14+
try {
15+
// determine directory path (use current directory when none provided)
16+
let directoryPath;
17+
if (cliArguments.length === 0) {
18+
directoryPath = ".";
19+
} else {
20+
directoryPath = cliArguments[0];
21+
}
22+
23+
// read directory entries
24+
const directoryEntries = await fs.readdir(directoryPath);
25+
26+
// filter out dotfiles unless --all was provided
27+
const visibleEntries = [];
28+
if (cliOptions.all) {
29+
for (const name of directoryEntries) {
30+
visibleEntries.push(name);
31+
}
32+
} else {
33+
for (const name of directoryEntries) {
34+
if (!name.startsWith(".")) {
35+
visibleEntries.push(name);
36+
}
37+
}
38+
}
39+
40+
// build output
41+
let outputString = "";
42+
if (cliOptions.onePerLine) {
43+
for (const name of visibleEntries) {
44+
outputString += name + "\n";
45+
}
46+
// if there are no entries, outputString stays empty
47+
} else {
48+
for (let i = 0; i < visibleEntries.length; i++) {
49+
if (i > 0) {
50+
outputString += " ";
51+
}
52+
outputString += visibleEntries[i];
53+
}
54+
if (outputString !== "") {
55+
outputString += "\n";
56+
}
57+
}
58+
59+
process.stdout.write(outputString);
60+
} catch (err) {
61+
console.error("Error reading directory:", err);
62+
process.exitCode = 1;
63+
}
64+
}
65+
66+
runLsCommand();

0 commit comments

Comments
 (0)