Find a file or directory by walking up parent directories. This library provides a comprehensive set of functions for traversing filesystem hierarchies upward from a starting directory to locate files or directories by name, pattern, or custom matcher function.
npm install find-upimport {
findUp,
findUpSync,
findUpMultiple,
findUpMultipleSync,
findUpStop,
pathExists,
pathExistsSync,
type Match,
type Options
} from "find-up";For specific imports:
import { findUp } from "find-up";
import { pathExists } from "find-up";import path from 'node:path';
import { findUp, pathExists } from 'find-up';
// Find a single file by name
console.log(await findUp('package.json'));
//=> '/Users/sindresorhus/project/package.json'
// Find from multiple possible names
console.log(await findUp(['config.json', 'config.js']));
//=> '/Users/sindresorhus/project/config.js'
// Find using a custom matcher function
console.log(await findUp(async directory => {
const hasPackageJson = await pathExists(path.join(directory, 'package.json'));
return hasPackageJson && directory;
}, {type: 'directory'}));
//=> '/Users/sindresorhus/project'find-up is built around a simple but powerful directory traversal pattern with several key architectural components:
findUp) and multiple-result (findUpMultiple) search patternsfindUpStop symbol and configurable stopping pointspath-exists library for robust filesystem existence checkingThe library follows a consistent API pattern where each core function has both async and sync variants, and each supports both simple name-based matching and custom matcher function approaches.
Find the first occurrence of a file or directory by walking up parent directories.
/**
* Find a file or directory by walking up parent directories (async)
* @param name - Name or array of names to search for
* @param options - Search configuration options
* @returns Promise resolving to the first path found or undefined
*/
function findUp(name: string | readonly string[], options?: Options): Promise<string | undefined>;
/**
* Find a file or directory using a custom matcher function (async)
* @param matcher - Function called for each directory in the search
* @param options - Search configuration options
* @returns Promise resolving to the first path found or undefined
*/
function findUp(matcher: (directory: string) => (Match | Promise<Match>), options?: Options): Promise<string | undefined>;
/**
* Find a file or directory by walking up parent directories (sync)
* @param name - Name or array of names to search for
* @param options - Search configuration options
* @returns The first path found or undefined
*/
function findUpSync(name: string | readonly string[], options?: Options): string | undefined;
/**
* Find a file or directory using a custom matcher function (sync)
* @param matcher - Function called for each directory in the search
* @param options - Search configuration options
* @returns The first path found or undefined
*/
function findUpSync(matcher: (directory: string) => Match, options?: Options): string | undefined;Find all occurrences of a file or directory by walking up parent directories.
/**
* Find files or directories by walking up parent directories (async)
* @param name - Name or array of names to search for
* @param options - Search configuration options
* @returns Promise resolving to array of all paths found
*/
function findUpMultiple(name: string | readonly string[], options?: Options): Promise<string[]>;
/**
* Find files or directories using a custom matcher function (async)
* @param matcher - Function called for each directory in the search
* @param options - Search configuration options
* @returns Promise resolving to array of all paths found
*/
function findUpMultiple(matcher: (directory: string) => (Match | Promise<Match>), options?: Options): Promise<string[]>;
/**
* Find files or directories by walking up parent directories (sync)
* @param name - Name or array of names to search for
* @param options - Search configuration options
* @returns Array of all paths found
*/
function findUpMultipleSync(name: string | readonly string[], options?: Options): string[];
/**
* Find files or directories using a custom matcher function (sync)
* @param matcher - Function called for each directory in the search
* @param options - Search configuration options
* @returns Array of all paths found
*/
function findUpMultipleSync(matcher: (directory: string) => Match, options?: Options): string[];Utility functions for checking if files or directories exist.
/**
* Check if a path exists (async)
* @param path - Path to check for existence
* @returns Promise resolving to true if path exists, false otherwise
*/
function pathExists(path: string): Promise<boolean>;
/**
* Check if a path exists (sync)
* @param path - Path to check for existence
* @returns True if path exists, false otherwise
*/
function pathExistsSync(path: string): boolean;Symbol for controlling search behavior in matcher functions.
/**
* Symbol that can be returned by a matcher function to stop the search
* and force findUp to immediately return undefined
*/
const findUpStop: unique symbol;/**
* Possible return values from matcher functions
*/
type Match = string | typeof findUpStop | undefined;
/**
* Base options from locate-path library
*/
interface LocatePathOptions {
/** Directory to start the search from (default: process.cwd()) */
readonly cwd?: URL | string;
/** Type of path to match: 'file' or 'directory' (default: 'file') */
readonly type?: 'file' | 'directory';
/** Allow symbolic links to match if they point to the chosen path type (default: true) */
readonly allowSymlinks?: boolean;
}
/**
* Configuration options for find-up functions (extends locate-path options)
*/
type Options = {
/** Directory path where the search halts if no matches are found (default: root directory) */
readonly stopAt?: string;
} & LocatePathOptions;import { findUp } from 'find-up';
// Find the nearest package.json
const packagePath = await findUp('package.json');
console.log(packagePath);
//=> '/Users/sindresorhus/project/package.json'
// Find any of several config file types
const configPath = await findUp(['.eslintrc.js', '.eslintrc.json', '.eslintrc.yml']);
console.log(configPath);
//=> '/Users/sindresorhus/project/.eslintrc.json'import path from 'node:path';
import { findUp, pathExists, findUpStop } from 'find-up';
// Find a directory containing both package.json and src/
const projectRoot = await findUp(async directory => {
const hasPackage = await pathExists(path.join(directory, 'package.json'));
const hasSrc = await pathExists(path.join(directory, 'src'));
return hasPackage && hasSrc ? directory : undefined;
}, { type: 'directory' });
// Stop search early for performance
const workspacePath = await findUp(directory => {
return path.basename(directory) === 'work' ? findUpStop : 'workspace.json';
});import { findUpMultiple } from 'find-up';
// Find all package.json files up the directory tree
const allPackageFiles = await findUpMultiple('package.json');
console.log(allPackageFiles);
//=> [
// '/Users/sindresorhus/project/packages/cli/package.json',
// '/Users/sindresorhus/project/package.json'
// ]import { findUpSync, pathExistsSync } from 'find-up';
// Synchronous file finding
const configPath = findUpSync('config.json');
// Synchronous path checking
const exists = pathExistsSync('/path/to/file.txt');import { findUp } from 'find-up';
// Start search from specific directory
const result = await findUp('target.txt', {
cwd: '/Users/sindresorhus/deep/nested/path'
});
// Look for directories instead of files
const dirResult = await findUp('node_modules', {
type: 'directory'
});
// Stop search at specific directory
const limitedResult = await findUp('file.txt', {
stopAt: '/Users/sindresorhus'
});
// Disable symlink following
const noSymlinksResult = await findUp('file.txt', {
allowSymlinks: false
});import { findUp } from 'find-up';
// Find project root by looking for common project indicators
const projectRoot = await findUp([
'package.json',
'cargo.toml',
'go.mod',
'.git'
], { type: 'directory' });import path from 'node:path';
import { findUp, pathExists } from 'find-up';
// Find and load the nearest configuration file
const configPath = await findUp(async directory => {
const candidates = [
path.join(directory, 'my-tool.config.js'),
path.join(directory, 'my-tool.config.json'),
path.join(directory, '.my-toolrc')
];
for (const candidate of candidates) {
if (await pathExists(candidate)) {
return candidate;
}
}
return undefined;
});import { findUp, findUpStop } from 'find-up';
// Stop search early to avoid traversing the entire filesystem
const result = await findUp(directory => {
// Stop if we've reached a system directory
if (directory === '/usr' || directory === '/opt') {
return findUpStop;
}
// Continue searching for our target
return 'my-file.txt';
});