0
# Klaw Sync
1
2
Klaw Sync is a fast, synchronous file system walker for Node.js that recursively traverses directories and returns an array of objects containing file paths and their corresponding fs.Stats instances. It is the synchronous counterpart to the popular klaw library.
3
4
## Package Information
5
6
- **Package Name**: klaw-sync
7
- **Package Type**: npm
8
- **Language**: JavaScript
9
- **Installation**: `npm install klaw-sync`
10
11
## Core Imports
12
13
```javascript
14
const klawSync = require('klaw-sync');
15
```
16
17
ES6 modules:
18
19
```javascript
20
import klawSync from 'klaw-sync';
21
```
22
23
## Basic Usage
24
25
```javascript
26
const klawSync = require('klaw-sync');
27
28
// Basic directory traversal
29
const items = klawSync('/some/directory');
30
// Returns: [{ path: '/some/directory/file1.txt', stats: fs.Stats }, ...]
31
32
// Get only files
33
const files = klawSync('/some/directory', { nodir: true });
34
35
// Get only directories
36
const dirs = klawSync('/some/directory', { nofile: true });
37
38
// Filter results
39
const jsFiles = klawSync('/project', {
40
filter: item => item.path.endsWith('.js')
41
});
42
```
43
44
## Capabilities
45
46
### Directory Walking
47
48
Recursively walk a directory tree and return all files and directories with their stats.
49
50
```javascript { .api }
51
/**
52
* Synchronously walk a directory tree
53
* @param {string} directory - Path to directory to traverse (resolved to absolute path)
54
* @param {Object} [options] - Configuration options
55
* @param {boolean} [options.nodir] - Return only files (ignore directories)
56
* @param {boolean} [options.nofile] - Return only directories (ignore files)
57
* @param {number} [options.depthLimit=-1] - Number of levels to recurse (-1 for unlimited)
58
* @param {Object} [options.fs] - Custom fs implementation (defaults to graceful-fs)
59
* @param {Function} [options.filter] - Filter function to include/exclude items
60
* @param {boolean} [options.traverseAll] - Traverse all subdirectories regardless of filter
61
* @param {Array} [ls] - Internal accumulator array (not for public use)
62
* @returns {Array<Object>} Array of objects with path and stats properties
63
*/
64
function klawSync(directory, options, ls);
65
```
66
67
**Parameters:**
68
69
- `directory` (string): The path to the directory to traverse. Will be resolved to an absolute path.
70
- `options` (Object, optional): Configuration options:
71
- `nodir` (boolean): When true, returns only files and ignores directories
72
- `nofile` (boolean): When true, returns only directories and ignores files
73
- `depthLimit` (number, default: -1): The number of directory levels to recurse. -1 means unlimited depth. Internally sets `rootDepth` for depth calculations
74
- `fs` (Object, default: graceful-fs): Custom filesystem implementation for testing or mocking
75
- `filter` (Function): Filter function that receives `{path, stats}` and returns boolean to include/exclude
76
- `traverseAll` (boolean): When true, traverses all subdirectories even if they don't pass the filter. When false (default), filtered-out directories are not explored
77
- `ls` (Array, internal): Internal accumulator array used for recursive calls. Do not provide this parameter in normal usage
78
79
**Returns:**
80
81
Array of objects with the following structure:
82
```javascript { .api }
83
interface WalkItem {
84
path: string; // Full absolute path to the file or directory
85
stats: fs.Stats; // Node.js fs.Stats object with file system information
86
}
87
```
88
89
**Important Behavior Notes:**
90
91
- **Symlink Handling**: Uses `lstatSync()` internally - symbolic links are treated as files with their own stats, not their targets. Symlinks are not followed.
92
- **Path Resolution**: The input directory path is automatically resolved to an absolute path.
93
- **Filter vs TraverseAll**: When `traverseAll: false` (default), directories that don't pass the filter function are not explored. When `traverseAll: true`, all subdirectories are explored regardless of filter results, but individual items are still subject to filtering for inclusion in results.
94
95
**Usage Examples:**
96
97
```javascript
98
const path = require('path');
99
const klawSync = require('klaw-sync');
100
101
// Basic usage - get all files and directories
102
const allItems = klawSync('/project');
103
console.log(allItems);
104
// [
105
// { path: '/project/src', stats: Stats { ... } },
106
// { path: '/project/src/index.js', stats: Stats { ... } },
107
// { path: '/project/package.json', stats: Stats { ... } }
108
// ]
109
110
// Files only
111
const files = klawSync('/project', { nodir: true });
112
113
// Directories only
114
const directories = klawSync('/project', { nofile: true });
115
116
// Limit depth to 2 levels
117
const shallow = klawSync('/project', { depthLimit: 2 });
118
119
// Filter for JavaScript files only
120
const jsFiles = klawSync('/project', {
121
filter: item => path.extname(item.path) === '.js'
122
});
123
124
// Hide hidden files and directories
125
const visible = klawSync('/project', {
126
filter: item => {
127
const basename = path.basename(item.path);
128
return basename === '.' || basename[0] !== '.';
129
}
130
});
131
132
// Filter by modification time (with traverseAll to ensure subdirectories are still explored)
133
const recent = klawSync('/project', {
134
filter: item => item.stats.mtime.getTime() > Date.now() - 86400000, // 24 hours
135
traverseAll: true
136
});
137
138
// Using custom fs (useful for testing with memfs)
139
const { fs: memfs } = require('memfs');
140
const memItems = klawSync('/virtual/path', { fs: memfs });
141
```
142
143
## Error Handling
144
145
The function throws standard Node.js filesystem errors:
146
147
- **ENOENT**: When the source directory does not exist
148
- **ENOTDIR**: When the source path is not a directory
149
- **EACCES**: When lacking permissions to read a directory
150
- **Other fs errors**: Any errors from the underlying filesystem operations
151
152
```javascript
153
const klawSync = require('klaw-sync');
154
155
try {
156
const items = klawSync('/some/directory');
157
console.log(`Found ${items.length} items`);
158
} catch (error) {
159
if (error.code === 'ENOENT') {
160
console.error('Directory does not exist');
161
} else if (error.code === 'ENOTDIR') {
162
console.error('Path is not a directory');
163
} else {
164
console.error('Error walking directory:', error);
165
}
166
}
167
```
168
169
## Performance
170
171
Klaw Sync is optimized for performance and consistently outperforms similar libraries like walk-sync. Benchmark results show approximately 2x faster performance across different directory sizes:
172
173
- Small directories (1,110 files): ~160 ops/sec vs ~80 ops/sec
174
- Medium directories (11,110 files): ~15 ops/sec vs ~7.5 ops/sec
175
- Large directories (111,110 files): ~1.2 ops/sec vs ~0.6 ops/sec
176
177
The library uses:
178
- Synchronous operations with minimal overhead
179
- Direct fs.lstatSync calls for file stats
180
- Efficient recursive traversal with accumulator pattern
181
- graceful-fs for enhanced reliability
182
183
## Types
184
185
```javascript { .api }
186
interface WalkOptions {
187
nodir?: boolean;
188
nofile?: boolean;
189
depthLimit?: number;
190
fs?: FileSystem;
191
filter?: (item: WalkItem) => boolean;
192
traverseAll?: boolean;
193
}
194
195
interface WalkItem {
196
path: string;
197
stats: fs.Stats;
198
}
199
200
interface FileSystem {
201
readdirSync(path: string): string[];
202
lstatSync(path: string): fs.Stats;
203
}
204
205
// Key fs.Stats properties used by klaw-sync and commonly accessed
206
interface fs.Stats {
207
isFile(): boolean;
208
isDirectory(): boolean;
209
isSymbolicLink(): boolean;
210
size: number;
211
mtime: Date; // modification time
212
ctime: Date; // change time
213
atime: Date; // access time
214
birthtime: Date; // creation time
215
mode: number; // file permissions
216
uid: number; // user ID
217
gid: number; // group ID
218
}
219
```