2

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.

migrated from serverfault.com May 2 '14 at 10:56

This question came from our site for system and network administrators.

  • 2
    Have you tried find with the -depth option? -depth Process each directory's contents before the directory itself.. – Zoredache Apr 29 '14 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 '14 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 '14 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 '14 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 '14 at 15:48
0
find_backwards () {
  test $# -ne 1 && return 2
  if [ -z "$find_backwards_recurse" ]; then
    pushd . &>/dev/null
    find_backwards_recurse=yes
  fi
  if [ -f "$1" ]; then
    echo "${PWD}/${1}"
    popd &>/dev/null
    find_backwards_recurse=
    return 0
  else
    if [ / != "$PWD" ]; then
      cd ..
      find_backwards "$1"
    else
      popd &>/dev/null
      find_backwards_recurse=
      return 1
    fi
  fi
}

start cmd:> pwd
/home/hl/tmp/tmp

start cmd:> find_backwards foo
/home/hl/tmp/foo
0

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

One possible script implementation.
rfind:

#!/bin/bash
d=$1
[[ -f  "$d/$2" ]] && echo  "$d/$2" 
until  [[ ${d%%*/*} ]] || [[ -z  "$d"  ]]
do
   d=${d%/*}
   [[ -f  "$d/$2" ]] && echo  "$d/$2" 
done  

Usage rfind path filename

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy