Find command for lookup up a directory tree

find

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.

Best Answer

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 path of $PWD. If it's not on the way to the current directory, it is pruned from the search path.

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

The bit after -prune simply 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
/home/kk/local/build/ast/build/src/cmd/ksh93/sh
$ find / -exec bash -c '[[ $PWD != "$1"* ]]' bash {} \; -prune -name bin -print
/bin
/home/kk/local/bin
/home/kk/local/build/ast/bin

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
Related Question