mrkeyoor.com_
Sat 08 Aug 22:53 UTC
npmUtilsupdated 08 Aug 2026

fs-exists-sync

fs-exists-sync is a zero-dependency CommonJS function for synchronously checking a filesystem path. It first calls Node's fs.accessSync, or fs.statSync on very old Node versions, and returns the original path string when that succeeds. On Linux, a failed check falls back to reading the parent directory and performs a case-insensitive filename search, returning the resolved spelling it finds. Missing paths, empty values, and non-string inputs return false. Despite its README description, that string-or-false contract is not identical to the boolean returned by fs.existsSync.

Verdict

Do not add this merely to replace fs.existsSync; its return type and Linux case-recovery logic make it less predictable than the built-in. Keep it only where existing code intentionally depends on those exact semantics.

API stability4/5There has been only one published version, 0.1.0 from April 2016, so consumers have seen no release churn. The exported function and its string-or-false behavior are fixed in a very small source file, but there is no semantic-version history, compatibility statement, declaration file, or active release practice to show how a future correction would be handled.
Docs2/5The README gives installation and several useful true-or-false-looking examples, documents empty and missing inputs, and explains how competing packages differed in 2016. It does not clearly state that success returns a path string, barely exposes the Linux case-insensitive directory scan, has an empty API section, and does not cover permission errors, synchronous cost, TypeScript, ESM, or modern built-in alternatives.
Maintenance1/5npm records a single release on April 9, 2016, and GitHub reports the last push on September 1, 2017. The repository is not archived and shows one open issue or PR, yet there have been no releases for modern Node versions, no declarations, no CI refresh, and no source changes addressing the mismatch between the advertised drop-in behavior and the actual return value.
Ecosystem2/5The npm downloads endpoint counted 3,286,015 downloads for July 31 through August 6, 2026, but the repository has only 12 stars and the package has no extensions or integrations. Its API wraps functionality already present in Node core, so the high traffic is likely dominated by transitive legacy dependency trees rather than a distinct active ecosystem.

Use it if

  • You maintain old CommonJS code that relies on receiving the matched path string rather than a true boolean
  • You deliberately want a wrong-case filename such as readme.md to resolve to README.md on Linux
  • You support ancient Node.js versions and need the package's accessSync-to-statSync fallback without dependencies
Skip it if

Setup reality

npm install fs-exists-sync is the whole installation: there are no runtime dependencies, peer dependencies, native extensions, environment variables, credentials, or config files. The surprises start at the return value. require('fs-exists-sync') produces a function whose successful result is a string, normally the exact input, and whose failure result is false. Code using strict comparisons such as exists(path) === true will therefore fail even when the path exists. On Linux, any access error triggers a synchronous fallback: the implementation resolves the path, tries readdirSync on it, then on its parent, and compares entries without case. A request for readme.md can return an absolute path ending in README.md. That scan happens not only for ENOENT but for any caught access error, including permission failures, and large directories make misses more expensive. It accepts only non-empty strings, so Buffer and URL path values supported by modern Node filesystem APIs return false. Relative paths are resolved against process.cwd(), as usual, and checking before a later open still has the standard time-of-check/time-of-use race. The package is CommonJS-only and bundles no TypeScript declaration; modern projects must use interop or add a local string-or-false type. For new Node code, built-in fs.existsSync is usually the simpler setup and behavior.

Patterns

Check a path with a truthy testcheck-path

const exists = require('fs-exists-sync');

if (exists('config.json')) {
  console.log('config exists');
}

Use truthiness, not === true. A successful check returns the input path string rather than the boolean true.

Capture the returned pathcapture-matched-path

const exists = require('fs-exists-sync');

const found = exists('README.md');
if (found !== false) {
  console.log('found at', found);
}

On an ordinary successful access, found is exactly the string passed in. It is not automatically absolute.

Recover actual filename casing on Linuxrecover-filename-case

const exists = require('fs-exists-sync');

const found = exists('./readme.md');
if (found) {
  console.log(found);
  // May print an absolute path ending in README.md on Linux
}

The case-insensitive parent-directory scan runs only after the first access fails and only when process.platform is linux.

Check whether a directory path existscheck-directory

const exists = require('fs-exists-sync');

const directory = exists('./fixtures');
if (directory) {
  console.log('directory is present');
}

Files and directories both count. This function does not tell you which kind matched.

Check existence, then require a regular filedistinguish-file

const fs = require('node:fs');
const exists = require('fs-exists-sync');

const found = exists('./settings.json');
const isFile = found !== false && fs.statSync(found).isFile();

This adds a second synchronous filesystem call and still has a race between checks. Open the file directly when the next operation can handle ENOENT.

Use a default when a config file is absentuse-default-value

const exists = require('fs-exists-sync');

const configPath = exists('./app.config.json') || './defaults.json';
console.log(configPath);

The expression works because the function returns either a non-empty path string or false.

Observe invalid input behaviorreject-invalid-input

const exists = require('fs-exists-sync');

console.log(exists());       // false
console.log(exists(''));     // false
console.log(exists(42));     // false

Only non-empty strings are accepted. Modern fs APIs may accept Buffer or URL values, but this wrapper rejects them.

Prefer opening directly when you need the fileavoid-exists-race

const fs = require('node:fs');

try {
  const text = fs.readFileSync('./config.json', 'utf8');
  console.log(text);
} catch (error) {
  if (error.code !== 'ENOENT') throw error;
  console.log('use defaults');
}

Checking and then opening is inherently racy. Handling the actual operation's ENOENT is safer and does not require this package.

Load the CommonJS function from Node ESMload-from-esm

import { createRequire } from 'node:module';

const require = createRequire(import.meta.url);
const exists = require('fs-exists-sync');

console.log(Boolean(exists('./package.json')));

Version 0.1.0 has no native ESM export. Some toolchains synthesize a default import, but createRequire makes Node behavior explicit.

Add the real return type in TypeScriptdeclare-types

declare module 'fs-exists-sync' {
  function exists(filepath?: unknown): string | false;
  export = exists;
}

The package ships no declarations. Do not type the result as boolean because successful calls return a string.

Alternatives

PackageRegistryPick it when
path-existsnpmYou want a maintained ESM helper with both asynchronous and synchronous boolean checks
file-existsnpmYou specifically need to know that a path is a file rather than a directory
fs-extranpmYou already need higher-level copy, move, empty, and ensure helpers alongside path checks