0
# Directory Operations
1
2
High-performance directory reading operations with intelligent caching, multiple output formats, and error handling. All operations cache results to minimize filesystem calls on subsequent accesses.
3
4
## Capabilities
5
6
### Asynchronous Directory Reading
7
8
Read directory contents asynchronously with configurable output formats.
9
10
```typescript { .api }
11
/**
12
* Read directory contents asynchronously
13
* @param entry - Directory to read (defaults to current working directory)
14
* @param opts - Options controlling output format
15
* @returns Promise resolving to array of Path objects or strings
16
*/
17
readdir(): Promise<PathBase[]>;
18
readdir(opts: { withFileTypes: true }): Promise<PathBase[]>;
19
readdir(opts: { withFileTypes: false }): Promise<string[]>;
20
readdir(opts: { withFileTypes: boolean }): Promise<PathBase[] | string[]>;
21
readdir(entry: PathBase | string): Promise<PathBase[]>;
22
readdir(entry: PathBase | string, opts: { withFileTypes: true }): Promise<PathBase[]>;
23
readdir(entry: PathBase | string, opts: { withFileTypes: false }): Promise<string[]>;
24
readdir(entry: PathBase | string, opts: { withFileTypes: boolean }): Promise<PathBase[] | string[]>;
25
```
26
27
**Usage Examples:**
28
29
```typescript
30
import { PathScurry } from "path-scurry";
31
32
const pw = new PathScurry();
33
34
// Default: returns Path objects
35
const entries1 = await pw.readdir();
36
for (const entry of entries1) {
37
console.log(`${entry.name}: ${entry.getType()}`);
38
}
39
40
// Return string names only
41
const names = await pw.readdir({ withFileTypes: false });
42
console.log("Files:", names);
43
44
// Read specific directory
45
const srcFiles = await pw.readdir("./src");
46
const textFiles = srcFiles.filter(entry =>
47
entry.isFile() && entry.name.endsWith(".txt")
48
);
49
50
// Mixed usage with Path objects
51
const configDir = await pw.readdir("./config", { withFileTypes: true });
52
for (const entry of configDir) {
53
if (entry.isFile()) {
54
console.log(`Config file: ${entry.fullpath()}`);
55
}
56
}
57
```
58
59
### Synchronous Directory Reading
60
61
Read directory contents synchronously with the same API as async version.
62
63
```typescript { .api }
64
/**
65
* Read directory contents synchronously
66
* @param entry - Directory to read (defaults to current working directory)
67
* @param opts - Options controlling output format
68
* @returns Array of Path objects or strings
69
*/
70
readdirSync(): PathBase[];
71
readdirSync(opts: { withFileTypes: true }): PathBase[];
72
readdirSync(opts: { withFileTypes: false }): string[];
73
readdirSync(opts: { withFileTypes: boolean }): PathBase[] | string[];
74
readdirSync(entry: PathBase | string): PathBase[];
75
readdirSync(entry: PathBase | string, opts: { withFileTypes: true }): PathBase[];
76
readdirSync(entry: PathBase | string, opts: { withFileTypes: false }): string[];
77
readdirSync(entry: PathBase | string, opts: { withFileTypes: boolean }): PathBase[] | string[];
78
```
79
80
**Usage Examples:**
81
82
```typescript
83
const pw = new PathScurry("/project");
84
85
// Synchronous directory reading
86
const entries = pw.readdirSync("src");
87
const jsFiles = entries.filter(entry =>
88
entry.isFile() && entry.name.endsWith(".js")
89
);
90
91
// Get just filenames
92
const fileNames = pw.readdirSync("dist", { withFileTypes: false });
93
console.log("Built files:", fileNames);
94
95
// Process directory structure
96
function listDirectory(path: string, level = 0) {
97
const indent = " ".repeat(level);
98
const entries = pw.readdirSync(path);
99
100
for (const entry of entries) {
101
console.log(`${indent}${entry.name} (${entry.getType()})`);
102
if (entry.isDirectory()) {
103
listDirectory(entry.fullpath(), level + 1);
104
}
105
}
106
}
107
108
listDirectory("./");
109
```
110
111
### Path Object Directory Methods
112
113
Directory operations available directly on Path objects.
114
115
```typescript { .api }
116
/**
117
* Read directory contents for this Path object
118
* @returns Promise resolving to array of child Path objects
119
*/
120
readdir(): Promise<PathBase[]>;
121
122
/**
123
* Read directory contents synchronously for this Path object
124
* @returns Array of child Path objects
125
*/
126
readdirSync(): PathBase[];
127
128
/**
129
* Node-style callback interface for directory reading
130
* @param cb - Callback function receiving (error, entries)
131
* @param allowZalgo - Whether to allow immediate callback execution
132
*/
133
readdirCB(
134
cb: (er: NodeJS.ErrnoException | null, entries: PathBase[]) => any,
135
allowZalgo?: boolean
136
): void;
137
138
/**
139
* Check if this path can be read as a directory
140
* @returns True if path is likely readable as directory
141
*/
142
canReaddir(): boolean;
143
144
/**
145
* Check if readdir has been successfully called on this path
146
* @returns True if directory contents are cached
147
*/
148
calledReaddir(): boolean;
149
150
/**
151
* Get cached directory contents without filesystem access
152
* @returns Array of cached child entries (may be empty if not cached)
153
*/
154
readdirCached(): PathBase[];
155
```
156
157
**Usage Examples:**
158
159
```typescript
160
const pw = new PathScurry();
161
const srcDir = pw.cwd.resolve("src");
162
163
// Direct Path object usage
164
if (srcDir.canReaddir()) {
165
const files = await srcDir.readdir();
166
console.log(`Found ${files.length} entries in src/`);
167
}
168
169
// Callback-style reading
170
srcDir.readdirCB((err, entries) => {
171
if (err) {
172
console.error("Failed to read directory:", err);
173
return;
174
}
175
176
console.log("Directory contents:", entries.map(e => e.name));
177
});
178
179
// Check cache status
180
if (srcDir.calledReaddir()) {
181
const cached = srcDir.readdirCached();
182
console.log("Cached entries:", cached.length);
183
} else {
184
console.log("Directory not yet read");
185
}
186
```
187
188
### Error Handling
189
190
Directory operations handle errors gracefully and return empty arrays when paths cannot be read.
191
192
**Error Scenarios:**
193
194
- **Non-existent directories**: Return empty array instead of throwing
195
- **Permission denied**: Return empty array, path marked accordingly
196
- **Not a directory**: Return empty array for files or other entry types
197
- **Filesystem errors**: Return empty array, error information cached
198
199
**Example:**
200
201
```typescript
202
const pw = new PathScurry();
203
204
// These all return empty arrays instead of throwing
205
const missing = await pw.readdir("./does-not-exist"); // []
206
const file = await pw.readdir("./package.json"); // []
207
const restricted = await pw.readdir("/root/.ssh"); // [] (if no permission)
208
209
// Check path status
210
const path = pw.cwd.resolve("./some-path");
211
if (path.isENOENT()) {
212
console.log("Path does not exist");
213
} else if (!path.canReaddir()) {
214
console.log("Path cannot be read as directory");
215
}
216
```
217
218
### Performance Considerations
219
220
- **First access**: Directory contents loaded from filesystem
221
- **Subsequent access**: Results served from cache (much faster)
222
- **Cache invalidation**: Manual invalidation not supported - assume filesystem is stable
223
- **Memory usage**: Controlled by `childrenCacheSize` option (default: 16384 entries)
224
- **Large directories**: Consider using streaming or iterator interfaces for directories with many entries