Is there any equivalent command, or options for, GNU find that will search up the directory tree? I'd like to look backwards through the tree for files with a given name. For example, say I'm in /usr/local/share/bin and I want to search look for a file called foo. Ideally I'd like the command to look for the file in the following order:

  1. /usr/local/share/bin/foo
  2. /usr/local/share/foo
  3. /usr/local/foo
  4. /usr/foo
  5. /foo

I know that I can write something like this as a shell function, but I was hoping there would be a command as rich as gnu find that I could leverage.

  • 2
    Have you tried find with the -depth option? -depth Process each directory's contents before the directory itself..
    – Zoredache
    Apr 29, 2014 at 5:54
  • As far as I can tell, the -depth switch just changes the find's mode of operation in terms of which directories it looks at first. It doesn't appear to make find look upwards through the directory hierarchy.
    – Bryan Kyle
    Apr 29, 2014 at 16:25
  • What exactly do you mean by upwards? When doing a tree search you either do depth first, or breadth first. A depth first search should return results like you describe above.
    – Zoredache
    Apr 29, 2014 at 16:36
  • find looks downwards through the directory structure, towards the leaves of the file system. I want to look upwards, meaning towards the root of the file system. See the list in my original question. Notice that it starts with a longer path (deeper in the file system) and moves towards towards short paths (shallower in the file system).
    – Bryan Kyle
    Apr 30, 2014 at 15:38
  • And how do you think a command could actually acomplish that? The is no magical way for a command to know the deepest folder. Are you going to pass the starting folder on the command line, or?
    – Zoredache
    Apr 30, 2014 at 15:48

4 Answers 4


The following uses find and would still search from the root directory down to the current directory, but would only look inside the directories on that single path:

find / -exec bash -c '[[ $PWD != "$1"* ]]' bash {} \; -prune -name foo -print

The first part of the command, up to the -prune, will determine whether the current pathname being examined is located in the $PWD path. It is pruned from the search path if it's not on the way to the current directory.

The comparison is carried out by a very short bash script that tests whether the current directory, $PWD, matches the start of the current pathname.

The bit after -prune tries to match foo against the filename that is being examined.

Example: Trying to find something called bin somewhere in the directory structure above where I'm currently at.

$ pwd
$ find / -exec bash -c '[[ $PWD/ != "${1%/}/"* ]]' bash {} \; -prune -name bin -print

The manipulations of the values of $PWD and $1 in the in-line script make sure that $1 (the thing found by find) can be detected as a complete directory component at the start of $PWD, and not just as a prefix string (so that /home/mat is not confused with, e.g., /home/matthew).

On systems without bash, or where there is a faster-to-start sh shell:

find / -exec sh -c 'case $PWD/ in ("${1%/}/"*) exit 1; esac' sh {} \; -prune -name bin -print
  • This post is excellent, an eye-opener, but I can't seem to find a web resource covering these kind of constructs. Any pointers?
    – bu5hman
    Jun 7, 2019 at 18:14
  • 1
    @bu5hman I have never read a tutorial on how to use find. I have, however, used it a lot and read its manual. I'm sorry, but I don't have a magic web site for you. Oh, yes I have... Continue answering questions here, and read other people's answers :-)
    – Kusalananda
    Jun 7, 2019 at 18:17
  • would I be right in understanding that an -exec can be inserted after any option to process the output at that stage of the search, to control what is passed to the next option?
    – bu5hman
    Jun 7, 2019 at 18:24
  • @bu5hman Yes, exactly. I did write a sort of "canonical answer" on the use of find ... -exec .... See Understanding the -exec option of `find`
    – Kusalananda
    Jun 7, 2019 at 19:19
  • 1
    @DanielWagner Ah, good, that just means you need / at the end of $PWD as well. Thanks, I'll update the answer.
    – Kusalananda
    Apr 16, 2022 at 5:46
find_backwards () {
  test $# -ne 1 && return 2
  if [ -z "$find_backwards_recurse" ]; then
    pushd . &>/dev/null
  if [ -f "$1" ]; then
    echo "${PWD}/${1}"
    popd &>/dev/null
    return 0
    if [ / != "$PWD" ]; then
      cd ..
      find_backwards "$1"
      popd &>/dev/null
      return 1

start cmd:> pwd

start cmd:> find_backwards foo

I don't know any command who would do that.

One possible script implementation.

[[ -f  "$d/$2" ]] && echo  "$d/$2" 
until  [[ ${d%%*/*} ]] || [[ -z  "$d"  ]]
   [[ -f  "$d/$2" ]] && echo  "$d/$2" 

Usage rfind path filename


Walking up the directory path

f=/home/bu5hman/test; file=${f##*/}; base=${f%/*}
while [ ! -z $base ]; do
    find $base -maxdepth 1 -name $file

You must log in to answer this question.