How can I synchronously check, using node.js, if a file or directory exists?

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() or fs.stat().
  • Edge Cases:
  • Broken symlinks: Handle with fs.lstatSync().
  • Permissions: Use fs.accessSync() with R_OK/W_OK.

Summary Table

MethodUse CaseReturns
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!

Leave a Reply

Your email address will not be published. Required fields are marked *