or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

directory-operations.mddirectory-walking.mdfilesystem-metadata.mdindex.mdpath-objects.mdpath-resolution.md

filesystem-metadata.mddocs/

0

# File System Metadata

1

2

Cached filesystem metadata operations providing efficient access to file statistics, symbolic link resolution, and real path determination. All operations cache results to minimize expensive filesystem calls.

3

4

## Capabilities

5

6

### File Statistics (lstat)

7

8

Get file metadata similar to Node's `fs.lstat()` but with caching and simplified return values.

9

10

```typescript { .api }

11

/**

12

* Get file statistics asynchronously

13

* @param entry - Path to analyze (defaults to current working directory)

14

* @returns Promise resolving to Path object with metadata, or undefined if error

15

*/

16

lstat(entry?: string | PathBase): Promise<PathBase | undefined>;

17

18

/**

19

* Get file statistics synchronously

20

* @param entry - Path to analyze (defaults to current working directory)

21

* @returns Path object with metadata, or undefined if error

22

*/

23

lstatSync(entry?: string | PathBase): PathBase | undefined;

24

```

25

26

**Usage Examples:**

27

28

```typescript

29

import { PathScurry } from "path-scurry";

30

31

const pw = new PathScurry();

32

33

// Async lstat

34

const fileInfo = await pw.lstat("package.json");

35

if (fileInfo) {

36

console.log(`File type: ${fileInfo.getType()}`);

37

console.log(`Size: ${fileInfo.size} bytes`);

38

console.log(`Modified: ${fileInfo.mtime}`);

39

console.log(`Is file: ${fileInfo.isFile()}`);

40

} else {

41

console.log("File does not exist or cannot be accessed");

42

}

43

44

// Sync lstat

45

const dirInfo = pw.lstatSync("./src");

46

if (dirInfo?.isDirectory()) {

47

console.log(`Directory depth: ${dirInfo.depth()}`);

48

}

49

50

// Using Path objects directly

51

const path = pw.cwd.resolve("./config.json");

52

const stats = await path.lstat();

53

if (stats) {

54

console.log(`Full path: ${stats.fullpath()}`);

55

console.log(`Is symlink: ${stats.isSymbolicLink()}`);

56

}

57

```

58

59

### Symbolic Link Resolution (readlink)

60

61

Resolve symbolic links to their target paths with optional return format control.

62

63

```typescript { .api }

64

/**

65

* Read symbolic link target asynchronously

66

* @param entry - Symbolic link to resolve (defaults to current working directory)

67

* @param opt - Control return format (Path object vs string)

68

* @returns Promise resolving to link target or undefined if not a symlink/error

69

*/

70

readlink(): Promise<string | undefined>;

71

readlink(opt: { withFileTypes: false }): Promise<string | undefined>;

72

readlink(opt: { withFileTypes: true }): Promise<PathBase | undefined>;

73

readlink(opt: { withFileTypes: boolean }): Promise<PathBase | string | undefined>;

74

readlink(entry: string | PathBase, opt?: { withFileTypes: false }): Promise<string | undefined>;

75

readlink(entry: string | PathBase, opt: { withFileTypes: true }): Promise<PathBase | undefined>;

76

readlink(entry: string | PathBase, opt: { withFileTypes: boolean }): Promise<string | PathBase | undefined>;

77

78

/**

79

* Read symbolic link target synchronously

80

* @param entry - Symbolic link to resolve

81

* @param opt - Control return format (Path object vs string)

82

* @returns Link target or undefined if not a symlink/error

83

*/

84

readlinkSync(entry?: string | PathBase): string | undefined;

85

readlinkSync(opt: { withFileTypes: false }): string | undefined;

86

readlinkSync(opt: { withFileTypes: true }): PathBase | undefined;

87

readlinkSync(opt: { withFileTypes: boolean }): PathBase | string | undefined;

88

readlinkSync(entry: string | PathBase, opt?: { withFileTypes: false }): string | undefined;

89

readlinkSync(entry: string | PathBase, opt: { withFileTypes: true }): PathBase | undefined;

90

readlinkSync(entry: string | PathBase, opt: { withFileTypes: boolean }): string | PathBase | undefined;

91

```

92

93

**Usage Examples:**

94

95

```typescript

96

const pw = new PathScurry();

97

98

// Read symlink target as string

99

const target = await pw.readlink("./symlink-to-file");

100

if (target) {

101

console.log(`Symlink points to: ${target}`);

102

}

103

104

// Read symlink target as Path object

105

const targetPath = await pw.readlink("./symlink-to-dir", { withFileTypes: true });

106

if (targetPath) {

107

console.log(`Target is directory: ${targetPath.isDirectory()}`);

108

console.log(`Target full path: ${targetPath.fullpath()}`);

109

}

110

111

// Using Path objects directly

112

const link = pw.cwd.resolve("./some-symlink");

113

if (link.canReadlink()) {

114

const resolved = await link.readlink();

115

if (resolved) {

116

console.log(`Link resolved to: ${resolved.fullpath()}`);

117

}

118

}

119

120

// Sync version

121

const syncTarget = pw.readlinkSync("./another-link");

122

if (syncTarget) {

123

console.log(`Synchronous readlink result: ${syncTarget}`);

124

}

125

```

126

127

### Real Path Resolution (realpath)

128

129

Resolve paths to their canonical absolute form, following all symbolic links.

130

131

```typescript { .api }

132

/**

133

* Resolve path to canonical absolute form asynchronously

134

* @param entry - Path to resolve (defaults to current working directory)

135

* @param opt - Control return format (Path object vs string)

136

* @returns Promise resolving to canonical path or undefined if error

137

*/

138

realpath(): Promise<string | undefined>;

139

realpath(opt: { withFileTypes: false }): Promise<string | undefined>;

140

realpath(opt: { withFileTypes: true }): Promise<PathBase | undefined>;

141

realpath(opt: { withFileTypes: boolean }): Promise<PathBase | string | undefined>;

142

realpath(entry: string | PathBase, opt?: { withFileTypes: false }): Promise<string | undefined>;

143

realpath(entry: string | PathBase, opt: { withFileTypes: true }): Promise<PathBase | undefined>;

144

realpath(entry: string | PathBase, opt: { withFileTypes: boolean }): Promise<string | PathBase | undefined>;

145

146

/**

147

* Resolve path to canonical absolute form synchronously

148

* @param entry - Path to resolve

149

* @param opt - Control return format (Path object vs string)

150

* @returns Canonical path or undefined if error

151

*/

152

realpathSync(): string | undefined;

153

realpathSync(opt: { withFileTypes: false }): string | undefined;

154

realpathSync(opt: { withFileTypes: true }): PathBase | undefined;

155

realpathSync(opt: { withFileTypes: boolean }): PathBase | string | undefined;

156

realpathSync(entry: string | PathBase, opt?: { withFileTypes: false }): string | undefined;

157

realpathSync(entry: string | PathBase, opt: { withFileTypes: true }): PathBase | undefined;

158

realpathSync(entry: string | PathBase, opt: { withFileTypes: boolean }): string | PathBase | undefined;

159

```

160

161

**Usage Examples:**

162

163

```typescript

164

const pw = new PathScurry();

165

166

// Resolve real path as string

167

const real = await pw.realpath("./some/path/with/symlinks");

168

if (real) {

169

console.log(`Real path: ${real}`);

170

}

171

172

// Resolve real path as Path object

173

const realPath = await pw.realpath("./complex/symlink/chain", { withFileTypes: true });

174

if (realPath) {

175

console.log(`Real path exists: ${!realPath.isENOENT()}`);

176

console.log(`Real path type: ${realPath.getType()}`);

177

}

178

179

// Direct Path object usage

180

const path = pw.cwd.resolve("./might-be-symlink");

181

const resolved = await path.realpath();

182

if (resolved) {

183

console.log(`Canonical path: ${resolved.fullpath()}`);

184

if (resolved !== path) {

185

console.log("Path was resolved through symlinks");

186

}

187

}

188

189

// Sync version

190

const syncReal = pw.realpathSync("./symlinked-directory");

191

if (syncReal) {

192

console.log(`Sync realpath: ${syncReal}`);

193

}

194

```

195

196

### Path Object Metadata Methods

197

198

Metadata operations available directly on Path objects with additional caching checks.

199

200

```typescript { .api }

201

/**

202

* Get cached lstat result without filesystem access

203

* @returns Path object if lstat has been called, undefined otherwise

204

*/

205

lstatCached(): PathBase | undefined;

206

207

/**

208

* Get cached readlink result without filesystem access

209

* @returns Cached link target or undefined if not cached

210

*/

211

readlinkCached(): PathBase | undefined;

212

213

/**

214

* Get cached realpath result without filesystem access

215

* @returns Cached real path or undefined if not cached

216

*/

217

realpathCached(): PathBase | undefined;

218

219

/**

220

* Check if readlink operation is likely to succeed

221

* @returns True if path might be a readable symbolic link

222

*/

223

canReadlink(): boolean;

224

225

/**

226

* Check if path is known to not exist

227

* @returns True if previous operations determined path doesn't exist

228

*/

229

isENOENT(): boolean;

230

```

231

232

**Usage Examples:**

233

234

```typescript

235

const path = pw.cwd.resolve("./some-file");

236

237

// Check cached status before expensive operations

238

const cachedStats = path.lstatCached();

239

if (cachedStats) {

240

console.log("Already have stats:", cachedStats.getType());

241

} else {

242

const stats = await path.lstat();

243

console.log("Fetched stats:", stats?.getType());

244

}

245

246

// Check if path is worth reading as symlink

247

if (path.canReadlink()) {

248

const target = await path.readlink();

249

console.log("Symlink target:", target?.fullpath());

250

} else {

251

console.log("Not a symlink or readlink would fail");

252

}

253

254

// Check existence status

255

if (path.isENOENT()) {

256

console.log("Path is known to not exist");

257

} else {

258

console.log("Path might exist (or status unknown)");

259

}

260

```

261

262

### Available Statistics Properties

263

264

Path objects expose filesystem statistics after successful `lstat()` calls:

265

266

```typescript { .api }

267

interface PathBase {

268

// File system statistics (available after lstat)

269

readonly dev?: number; // Device ID

270

readonly mode?: number; // File mode

271

readonly nlink?: number; // Number of hard links

272

readonly uid?: number; // User ID

273

readonly gid?: number; // Group ID

274

readonly rdev?: number; // Device ID (special files)

275

readonly blksize?: number; // Block size

276

readonly ino?: number; // Inode number

277

readonly size?: number; // File size in bytes

278

readonly blocks?: number; // Number of blocks

279

readonly atimeMs?: number; // Access time (milliseconds)

280

readonly mtimeMs?: number; // Modification time (milliseconds)

281

readonly ctimeMs?: number; // Status change time (milliseconds)

282

readonly birthtimeMs?: number; // Creation time (milliseconds)

283

readonly atime?: Date; // Access time

284

readonly mtime?: Date; // Modification time

285

readonly ctime?: Date; // Status change time

286

readonly birthtime?: Date; // Creation time

287

}

288

```

289

290

**Usage Example:**

291

292

```typescript

293

const fileInfo = await pw.lstat("./large-file.dat");

294

if (fileInfo) {

295

console.log(`File size: ${fileInfo.size} bytes`);

296

console.log(`Last modified: ${fileInfo.mtime}`);

297

console.log(`Inode: ${fileInfo.ino}`);

298

console.log(`Mode: ${fileInfo.mode?.toString(8)}`); // Octal permissions

299

}

300

```