This question already has an answer here:

So say I'm in a directory that is deep within a file structure, such as


I know that in either the current folder baz or one of the folders above me (such as home, cory, projects, foo, bar, or bash) there is a file named happy. How can I find that file without searching a lot of extra folders?

marked as duplicate by slm Mar 30 '15 at 12:30

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.


function upsearch () {
    test / == "$PWD" && return || test -e "$1" && echo "found: " "$PWD" && return || cd .. && upsearch "$1"

This function will walk up from the current dir. Note, that it is a function, and will change the directory, while traversing. It will stop in the directory, where it finds the file, and will walk up to the root / if not.

You might want to change it to a script instead of a function, and maybe jump back, if the file isn't found in the root directory.

If you never want to cd to the dir:

upsearch () {
  for (( n=${#slashes}; n>0; --n ))
    test -e "$directory/$1" && echo "$directory/$1" && return 

This will lead to results like /home/cory/a/b/c/../../../happy if the file is in /home/cory/. If you need a cleaned path, you could do some

cd "$directory"
echo "$PWD"
cd - 

on success.

  • Remember to quote your expansions. If $PWD has a space in your test will be broken by wordsplitting. – Chris Down Sep 20 '11 at 15:50
  • I added masking to the directories. Is it correct now? It will still fail with special characters like '*' in filenames, won't it? – user unknown Sep 21 '11 at 2:41

Take a look at the -mindepth and -maxdepth options to find.

find won't traverse directories in a backwards direction, but you can approach it in the regular direction and limit the depth of the search.

For example:

find /home /home/cory /home/cory/projects /home/cory/projects/foo /home/cory/projects/foo/bar /home/cory/projects/foo/bar/bash -maxdepth 0 -name happy -print
  • That's not going to help. Either you use -maxdepth 0 or -maxdepth 1, in which case find isn't useful, or you don't, in which case you traverse plenty of extraneous directories for no reason. – Gilles May 19 '11 at 23:02
  • It is a working solution. I have added an example to clarify this. – gjb May 19 '11 at 23:21
  • You're missing the step where you generate the list of directories from $PWD or some argument. And if you're going to do that, you don't need find (ok, you can call it, but it won't be very useful). – Gilles May 19 '11 at 23:24
  • The question was "How can I find that file without searching a lot of extra folders?". I accept that this might not be the most elegant solution, but it gets the job done without searching any extra folders. – gjb May 19 '11 at 23:32

I improved on @user-unknown's solution a bit by saving the current dir, performing an arbitrary test, then restoring the original dir before returning with response. It's more flexible because you can test for anything.

I also provide for an optional second argument that says how high to go.



# Use this script instead of ~/.rvm/bin/rvm-prompt
# and the output of rvm-prompt will show up in your command prompt
# only if you are in a Ruby project directory.

# see http://stackoverflow.com/a/4264351/270511
# and http://unix.stackexchange.com/questions/13464/is-there-a-way-to-find-a-file-in-an-inverse-recursive-search

upsearch () {

  while [[ "`pwd`" != "$up_to" && "`pwd`" != '/' ]]; do
    if eval "[[ $the_test ]]"; then
    cd ..
  cd $curdir
  return $result

if upsearch '-e Gemfile || ! -z "$(shopt -s nullglob; echo *.gemspec *.rb)"' ; then

Not the answer you're looking for? Browse other questions tagged or ask your own question.