or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

directory-operations.mdfile-descriptors.mdfile-operations.mdfile-watching.mdindex.mdstats-permissions.mdstreams.mdsymbolic-links.md

symbolic-links.mddocs/

0

# Symbolic Links

1

2

Symbolic link and hard link creation, reading, and path resolution with cross-platform support. Provides complete symlink functionality including link creation, target reading, and real path resolution.

3

4

## Capabilities

5

6

### Symbolic Link Creation

7

8

Create symbolic links pointing to other files or directories.

9

10

```javascript { .api }

11

/**

12

* Synchronously create a symbolic link

13

* @param target - Path that the symlink points to (can be relative or absolute)

14

* @param path - Path where the symlink will be created

15

* @param type - Link type (defaults to 'file', only 'file' is supported)

16

*/

17

symlinkSync(target: string | Buffer, path: string | Buffer, type?: string): void;

18

19

/**

20

* Asynchronously create a symbolic link

21

* @param target - Path that the symlink points to

22

* @param path - Path where the symlink will be created

23

* @param type - Link type (defaults to 'file')

24

* @param callback - Completion callback

25

*/

26

symlink(target: string | Buffer, path: string | Buffer, type?: string, callback?: (err?: Error) => void): void;

27

symlink(target: string | Buffer, path: string | Buffer, callback: (err?: Error) => void): void;

28

```

29

30

**Usage Examples:**

31

32

```javascript

33

// Create symlink to a file

34

fs.writeFileSync('/original.txt', 'Original content');

35

fs.symlinkSync('/original.txt', '/link-to-original.txt');

36

37

// Create symlink with relative target

38

fs.symlinkSync('../data/config.json', '/app/config.json');

39

40

// Create symlink to directory

41

fs.mkdirSync('/source-dir');

42

fs.symlinkSync('/source-dir', '/link-to-dir');

43

44

// Async symlink creation

45

fs.symlink('/target/file.txt', '/links/symlink.txt', (err) => {

46

if (!err) {

47

console.log('Symbolic link created');

48

}

49

});

50

51

// Promise-based symlink creation

52

await fs.promises.symlink('/source', '/destination-link');

53

```

54

55

### Reading Symbolic Links

56

57

Read the target path of symbolic links.

58

59

```javascript { .api }

60

/**

61

* Synchronously read the target of a symbolic link

62

* @param path - Path to the symbolic link

63

* @param options - Read options including encoding

64

* @returns Target path as string or Buffer

65

*/

66

readlinkSync(path: string | Buffer, options?: ReadlinkOptions): string | Buffer;

67

readlinkSync(path: string | Buffer, encoding: string): string | Buffer;

68

69

/**

70

* Asynchronously read the target of a symbolic link

71

* @param path - Path to the symbolic link

72

* @param options - Read options including encoding

73

* @param callback - Completion callback with target path

74

*/

75

readlink(path: string | Buffer, options?: ReadlinkOptions, callback?: (err?: Error, linkString?: string | Buffer) => void): void;

76

readlink(path: string | Buffer, encoding: string, callback: (err?: Error, linkString?: string | Buffer) => void): void;

77

readlink(path: string | Buffer, callback: (err?: Error, linkString?: string) => void): void;

78

79

interface ReadlinkOptions {

80

/** Encoding for returned path */

81

encoding?: string;

82

}

83

```

84

85

**Usage Examples:**

86

87

```javascript

88

// Create and read a symlink

89

fs.symlinkSync('/etc/config.conf', '/app/config.conf');

90

const target = fs.readlinkSync('/app/config.conf');

91

console.log('Symlink points to:', target); // '/etc/config.conf'

92

93

// Read with specific encoding

94

const targetBuffer = fs.readlinkSync('/app/config.conf', { encoding: 'buffer' });

95

console.log('Target as buffer:', targetBuffer);

96

97

// Read as UTF-8 string

98

const targetStr = fs.readlinkSync('/app/config.conf', 'utf8');

99

100

// Async readlink

101

fs.readlink('/app/config.conf', (err, target) => {

102

if (!err) {

103

console.log('Symlink target:', target);

104

}

105

});

106

107

// Promise-based readlink

108

const target = await fs.promises.readlink('/app/config.conf');

109

```

110

111

### Hard Link Creation

112

113

Create hard links that reference the same file data.

114

115

```javascript { .api }

116

/**

117

* Synchronously create a hard link

118

* @param existingPath - Path to existing file

119

* @param newPath - Path for the new hard link

120

*/

121

linkSync(existingPath: string | Buffer, newPath: string | Buffer): void;

122

123

/**

124

* Asynchronously create a hard link

125

* @param existingPath - Path to existing file

126

* @param newPath - Path for the new hard link

127

* @param callback - Completion callback

128

*/

129

link(existingPath: string | Buffer, newPath: string | Buffer, callback?: (err?: Error) => void): void;

130

```

131

132

**Usage Examples:**

133

134

```javascript

135

// Create original file

136

fs.writeFileSync('/original.txt', 'Shared content');

137

138

// Create hard link

139

fs.linkSync('/original.txt', '/hardlink.txt');

140

141

// Both files share the same content

142

console.log(fs.readFileSync('/original.txt', 'utf8')); // 'Shared content'

143

console.log(fs.readFileSync('/hardlink.txt', 'utf8')); // 'Shared content'

144

145

// Modifying one affects the other

146

fs.writeFileSync('/hardlink.txt', 'Modified content');

147

console.log(fs.readFileSync('/original.txt', 'utf8')); // 'Modified content'

148

149

// Async hard link creation

150

fs.link('/source.txt', '/another-link.txt', (err) => {

151

if (!err) {

152

console.log('Hard link created');

153

}

154

});

155

156

// Promise-based hard link

157

await fs.promises.link('/existing.txt', '/new-hardlink.txt');

158

```

159

160

### Real Path Resolution

161

162

Resolve absolute paths by following symbolic links.

163

164

```javascript { .api }

165

/**

166

* Synchronously resolve a path to its absolute real path

167

* @param path - Path to resolve (may contain symlinks)

168

* @returns Absolute real path with symlinks resolved

169

*/

170

realpathSync(path: string | Buffer): string;

171

172

/**

173

* Asynchronously resolve a path to its absolute real path

174

* @param path - Path to resolve (may contain symlinks)

175

* @param callback - Completion callback with resolved path

176

*/

177

realpath(path: string | Buffer, callback: (err?: Error, resolvedPath?: string) => void): void;

178

179

/**

180

* Native realpath implementation (same as realpath)

181

*/

182

realpathSync.native(path: string | Buffer): string;

183

realpath.native(path: string | Buffer, callback: (err?: Error, resolvedPath?: string) => void): void;

184

```

185

186

**Usage Examples:**

187

188

```javascript

189

// Create a chain of symlinks

190

fs.writeFileSync('/real-file.txt', 'content');

191

fs.symlinkSync('/real-file.txt', '/link1.txt');

192

fs.symlinkSync('/link1.txt', '/link2.txt');

193

194

// Resolve the real path

195

const realPath = fs.realpathSync('/link2.txt');

196

console.log(realPath); // '/real-file.txt'

197

198

// Resolve relative paths

199

fs.symlinkSync('../config/app.json', '/app/config.json');

200

const resolved = fs.realpathSync('/app/config.json');

201

console.log(resolved); // Absolute path to the actual file

202

203

// Async realpath

204

fs.realpath('/complex/symlink/path', (err, resolvedPath) => {

205

if (!err) {

206

console.log('Real path:', resolvedPath);

207

}

208

});

209

210

// Promise-based realpath

211

const realPath = await fs.promises.realpath('/symlink/chain');

212

213

// Use native implementation

214

const nativeRealPath = fs.realpathSync.native('/symlink');

215

```

216

217

### Link Detection and Statistics

218

219

Detect symbolic links and get their statistics.

220

221

```javascript { .api }

222

/**

223

* Get stats for a path without following symbolic links

224

* @param path - Path to get stats for

225

* @returns Stats object (symlinks return symlink stats, not target stats)

226

*/

227

lstatSync(path: string | Buffer): Stats;

228

229

/**

230

* Asynchronously get stats without following symbolic links

231

* @param path - Path to get stats for

232

* @param callback - Completion callback with stats

233

*/

234

lstat(path: string | Buffer, callback: (err?: Error, stats?: Stats) => void): void;

235

236

interface Stats {

237

/** Check if this is a symbolic link */

238

isSymbolicLink(): boolean;

239

/** Check if this is a regular file */

240

isFile(): boolean;

241

/** Check if this is a directory */

242

isDirectory(): boolean;

243

size: number;

244

mode: number;

245

// ... other properties

246

}

247

```

248

249

**Usage Examples:**

250

251

```javascript

252

// Create file and symlink

253

fs.writeFileSync('/target.txt', 'Hello World');

254

fs.symlinkSync('/target.txt', '/link.txt');

255

256

// Compare stat vs lstat

257

const fileStats = fs.statSync('/link.txt'); // Stats of target file

258

const linkStats = fs.lstatSync('/link.txt'); // Stats of symlink itself

259

260

console.log('File is symlink:', fileStats.isSymbolicLink()); // false

261

console.log('Link is symlink:', linkStats.isSymbolicLink()); // true

262

263

console.log('File size:', fileStats.size); // 11 (length of "Hello World")

264

console.log('Link size:', linkStats.size); // Length of target path string

265

266

// Check if path is a symlink

267

function isSymlink(path) {

268

try {

269

return fs.lstatSync(path).isSymbolicLink();

270

} catch (err) {

271

return false;

272

}

273

}

274

275

console.log('Is symlink:', isSymlink('/link.txt')); // true

276

277

// Async lstat

278

fs.lstat('/maybe-symlink.txt', (err, stats) => {

279

if (!err) {

280

if (stats.isSymbolicLink()) {

281

console.log('This is a symbolic link');

282

} else {

283

console.log('This is not a symbolic link');

284

}

285

}

286

});

287

```

288

289

## Advanced Link Operations

290

291

```javascript

292

// Follow symlink chain manually

293

function followSymlinkChain(path, maxDepth = 10) {

294

const chain = [];

295

let current = path;

296

let depth = 0;

297

298

while (depth < maxDepth) {

299

chain.push(current);

300

301

try {

302

const stats = fs.lstatSync(current);

303

if (!stats.isSymbolicLink()) {

304

break; // Reached the end

305

}

306

307

current = fs.readlinkSync(current);

308

depth++;

309

} catch (err) {

310

break;

311

}

312

}

313

314

return chain;

315

}

316

317

// Create backup with hard link

318

function createBackupHardLink(originalPath, backupPath) {

319

try {

320

fs.linkSync(originalPath, backupPath);

321

console.log('Backup created with hard link');

322

} catch (err) {

323

// Fallback to copy if hard link fails

324

fs.copyFileSync(originalPath, backupPath);

325

console.log('Backup created with copy');

326

}

327

}

328

329

// Safe symlink creation (check if target exists)

330

function createSafeSymlink(target, linkPath) {

331

// Check if target exists

332

if (!fs.existsSync(target)) {

333

throw new Error(`Target does not exist: ${target}`);

334

}

335

336

// Remove existing link if present

337

if (fs.existsSync(linkPath)) {

338

const stats = fs.lstatSync(linkPath);

339

if (stats.isSymbolicLink()) {

340

fs.unlinkSync(linkPath);

341

} else {

342

throw new Error(`Cannot create symlink: ${linkPath} already exists and is not a symlink`);

343

}

344

}

345

346

fs.symlinkSync(target, linkPath);

347

}

348

```

349

350

## Cross-Platform Considerations

351

352

```javascript

353

// Handle both Windows and POSIX paths in symlinks

354

function createCrossPlatformSymlink(target, linkPath) {

355

// Normalize path separators for the platform

356

const normalizedTarget = target.replace(/[/\\]/g, path.sep);

357

fs.symlinkSync(normalizedTarget, linkPath);

358

}

359

360

// Resolve symlinks with proper path handling

361

function resolveWithPlatformPaths(symlinkPath) {

362

const realPath = fs.realpathSync(symlinkPath);

363

return path.normalize(realPath);

364

}

365

```

366

367

## Error Handling

368

369

Common symbolic link errors:

370

371

- `ENOENT` - Target file/directory doesn't exist (readlink, realpath)

372

- `EEXIST` - Link path already exists (symlink, link)

373

- `EINVAL` - Path is not a symbolic link (readlink)

374

- `EPERM` - Cannot create hard link to directory

375

- `ELOOP` - Too many symbolic links (realpath)

376

- `ENOTDIR` - Component in path is not a directory