PHPackages                             loilo/find-up - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Utility &amp; Helpers](/categories/utility)
4. /
5. loilo/find-up

ActiveLibrary[Utility &amp; Helpers](/categories/utility)

loilo/find-up
=============

Find a file by walking up ancestor directories

1.2.0(6y ago)34131MITPHPPHP &gt;= 7.1CI failing

Since Jul 16Pushed 5y agoCompare

[ Source](https://github.com/loilo/find-up)[ Packagist](https://packagist.org/packages/loilo/find-up)[ RSS](/packages/loilo-find-up/feed)WikiDiscussions master Synced 3w ago

READMEChangelogDependencies (4)Versions (4)Used By (1)

 [![FindUp logo: a folder icon with an upwards arrow in front](find-up.svg)](find-up.svg)

FindUp
======

[](#findup)

[![Tests](https://camo.githubusercontent.com/342971ff7fa9634e0d67c6f4edde2efac8452663d3610abf6330c68bf9eedaf9/68747470733a2f2f62616467656e2e6e65742f6769746875622f636865636b732f6c6f696c6f2f66696e642d75702f6d6173746572)](https://github.com/loilo/find-up/actions)[![Version on packagist.org](https://camo.githubusercontent.com/27545ba25d4b53049fb0369a8913b26035638f62592c129a335e09305931c6b9/68747470733a2f2f62616467656e2e6e65742f7061636b61676973742f762f6c6f696c6f2f66696e642d7570)](https://packagist.org/packages/loilo/find-up)

Find a file by walking up ancestor directories (e.g. a `composer.json` from inside a project).

Installation
------------

[](#installation)

```
composer require loilo/find-up
```

Usage
-----

[](#usage)

### Basic Example

[](#basic-example)

```
/var/www
└── project
    ├── composer.json
    └── src
        └── foo
            ├── bar
            └── example.php

```

`example.php`:

```
use Loilo\FindUp\Up;

// Get the project's composer.json's path by
// walking up from /var/www/project/src/foo
Up::find('composer.json') === '/var/www/project/composer.json';
```

This is the most basic example how to use this package. The finder will look for a `composer.json` file, starting at the directory where `Up::find()` was called (which is `/var/www/project/src/foo`).

> **Note:** If there was no `composer.json` on the way up, the `find` method would return `null`.

### Starting Directory

[](#starting-directory)

As can be seen in the basic example above, the default starting directory is the one from where `Up::find()` is called. Alternatively, a starting directory can be passed to the `find` method as a second argument:

```
// Start from the current working directory
Up::find('composer.json', getcwd());
```

### Advanced Matching

[](#advanced-matching)

Instead of a file name to search for, a (non-string) callable may be passed as the `find` method's first argument. It will receive each encountered file on the way up and decides whether it is the searched file.

Assuming we're starting in the `example.php` from the basic example directory tree above, we can find the path to the `composer.json` with the following call:

```
Up::find(function ($file, $directory) {
  return $file === 'composer.json';
});
```

#### Stop Searching Prematurely

[](#stop-searching-prematurely)

You can stop the search before reaching the filesystem root by returning an `Up::stop()` call. For example, if you know that your `composer.json` is not found upwards from the `/var/www` folder, you can break out of the search:

```
Up::find(function ($file, $directory) {
  if ($directory === '/var/www') {
    return Up::stop();
  }

  return $file === 'composer.json';
});
```

When returning `Up::stop()`, the `Up::find()` method will return `null` by default.

You may however pass a path to the `stop()` method that will be used as the result. If the path is not absolute, it will be resolved against the current `$directory`:

```
Up::find(function ($file, $directory) {
  if ($directory === '/var/www') {
    return Up::stop('stop.txt');
  }

  return false;
}) === '/var/www/stop.txt';
```

> **Note:** In previous versions, the way to stop searching was to return the `Up::STOP` constant.
>
> This technique still works, but it's deprecated and it's recommended to use `Up::stop()` instead.

#### Skip Folder

[](#skip-folder)

If you are in a directory of which you're sure it does not contain the searched file, you may avoid walking through all its files by returning `Up::skip()`:

```
Up::find(function ($file, $directory) {
  // Skip "src" directories
  if (basename($directory) === 'src') {
    return Up::skip();
  }

  return $file === 'composer.json';
});
```

By default, the `Up::skip()` method will only skip the currently scanned directory. You may however pass a (positive) number that indicates how many levels of directories should be skipped.

```
...

// skip the current directory and its parent directory,
// continue with grandparent directory
return Up::skip(2)
```

> **Note:** In previous versions, the way to skip scanning a folder was to return the `Up::SKIP` constant.
>
> This technique still works, but it's deprecated and it's recommended to use `Up::skip()` instead.

#### Jump to Other Folder

[](#jump-to-other-folder)

If you want to stop searching the current directory tree altogether and continue from another path, you can return an `Up::jump()` call:

```
Up::find(function ($file, $directory) {
  if ($directory === '/var/www/project') {
    return Up::jump('/var/www/other-project');
  }

  return $file === 'composer.json';
});
```

> **Note:** You can only jump to a directory you have not previously visited in the current search. This serves to avoid infinite loops.

###  Health Score

28

—

LowBetter than 52% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity18

Limited adoption so far

Community8

Small or concentrated contributor base

Maturity56

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~22 days

Total

3

Last Release

2490d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/b1da49bad9203cc40a34d975dc00c80af09452bee1da6413e2f1b8214b539675?d=identicon)[loilo](/maintainers/loilo)

---

Top Contributors

[![loilo](https://avatars.githubusercontent.com/u/1922624?v=4)](https://github.com/loilo "loilo (17 commits)")

###  Code Quality

TestsPHPUnit

Code StylePHP\_CodeSniffer

### Embed Badge

![Health badge](/badges/loilo-find-up/health.svg)

```
[![Health](https://phpackages.com/badges/loilo-find-up/health.svg)](https://phpackages.com/packages/loilo-find-up)
```

###  Alternatives

[msp/cmsimportexport

76533.1k](/packages/msp-cmsimportexport)[hyperf/crontab

A crontab component for Hyperf.

131.6M71](/packages/hyperf-crontab)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
