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