In Node.js, you can synchronously check if a file or directory exists using the fs
(File System) module. Below are detailed methods with examples, covering edge cases and different scenarios.
1. Using fs.existsSync()
The simplest method to check existence (returns true
/false
).
Note: This only checks existence, not permissions or type (file vs. directory).
const fs = require('fs');
// Check if a FILE exists
const fileExists = fs.existsSync('file.txt');
console.log('File exists:', fileExists); // true/false
// Check if a DIRECTORY exists
const dirExists = fs.existsSync('my-directory');
console.log('Directory exists:', dirExists); // true/false
Key Points:
- Works for both files and directories.
- Not deprecated (unlike the callback-based
fs.exists
).
2. Using fs.accessSync()
Checks existence and permissions (e.g., read/write access). Throws an error if the path doesn’t exist.
Use try...catch
to handle errors gracefully.
const fs = require('fs');
function pathExists(path) {
try {
fs.accessSync(path, fs.constants.F_OK); // F_OK checks existence
return true;
} catch (err) {
return false;
}
}
// Example usage
console.log('File exists:', pathExists('file.txt')); // true/false
console.log('Directory exists:', pathExists('my-directory')); // true/false
Flags for fs.accessSync
:
fs.constants.F_OK
: Existence (default).fs.constants.R_OK
: Readable.fs.constants.W_OK
: Writable.
3. Using fs.statSync()
Checks existence and provides metadata (e.g., file/directory type).
Use try...catch
to handle missing paths.
const fs = require('fs');
function checkPath(path) {
try {
const stats = fs.statSync(path);
return {
exists: true,
isFile: stats.isFile(),
isDirectory: stats.isDirectory()
};
} catch (err) {
return { exists: false };
}
}
// Example usage
const result = checkPath('file.txt');
console.log(result);
// Output if exists: { exists: true, isFile: true, isDirectory: false }
// Output if missing: { exists: false }
4. Differentiating Files and Directories
Use fs.statSync()
to distinguish between files and directories:
const fs = require('fs');
function isDirectory(path) {
try {
return fs.statSync(path).isDirectory();
} catch (err) {
return false; // Path doesn't exist
}
}
// Example usage
console.log('Is directory:', isDirectory('my-directory')); // true/false
5. Handling Broken Symbolic Links
fs.existsSync()
returns false
for broken symlinks, while fs.statSync()
throws an error:
const fs = require('fs');
// Create a broken symlink: `ln -s non-existent.txt broken-link.txt`
console.log(fs.existsSync('broken-link.txt')); // false (even though the symlink exists)
6. Full Example: Combined Check
A utility function to check existence, type, and permissions:
const fs = require('fs');
function checkPathDetails(path) {
try {
const stats = fs.statSync(path);
const access = {
readable: fs.accessSync(path, fs.constants.R_OK) === undefined,
writable: fs.accessSync(path, fs.constants.W_OK) === undefined
};
return {
exists: true,
isFile: stats.isFile(),
isDirectory: stats.isDirectory(),
...access
};
} catch (err) {
return { exists: false };
}
}
// Example usage
console.log(checkPathDetails('file.txt'));
// Output if exists:
// { exists: true, isFile: true, isDirectory: false, readable: true, writable: true }
7. Key Notes
- Blocking the Event Loop: Synchronous methods (
*Sync
) block the event loop. Avoid them in performance-critical code. - Alternatives: For non-blocking checks, use asynchronous methods like
fs.promises.access()
orfs.stat()
. - Edge Cases:
- Broken symlinks: Handle with
fs.lstatSync()
. - Permissions: Use
fs.accessSync()
withR_OK
/W_OK
.
Summary Table
Method | Use Case | Returns |
---|---|---|
fs.existsSync() | Quick existence check (file/directory) | true /false |
fs.accessSync() | Existence + permissions (e.g., read/write) | Throws error if missing |
fs.statSync() | Existence + metadata (file/directory type) | fs.Stats object |
When to Use Which?
- Simple check:
fs.existsSync()
. - Check permissions:
fs.accessSync()
. - Check file type:
fs.statSync()
.
By mastering these methods, you can reliably manage file/directory checks in Node.js!