Shell – Find a specific file in the nearest ancestor of the current working directory

directoryfilesfindshell-script

I'd like to find a way to find a given file by looking upward in the directory structure, rather than recursively searching through child directories.

There's a node module that appears to do exactly what I want, but I don't want to depend on installing JavaScript or packages like that. Is there a shell command for this? A way to make find do that? Or a standard approach that I just wasn't able to find through Googling?

Best Answer

This is a direct translation of the find-config algorithm in generic shell commands (tested under bash, ksh, and zsh), where I use a return code of 0 to mean success and 1 to mean NULL/failure.

findconfig() {
  # from: https://www.npmjs.com/package/find-config#algorithm
  # 1. If X/file.ext exists and is a regular file, return it. STOP
  # 2. If X has a parent directory, change X to parent. GO TO 1
  # 3. Return NULL.

  if [ -f "$1" ]; then
    printf '%s\n' "${PWD%/}/$1"
  elif [ "$PWD" = / ]; then
    false
  else
    # a subshell so that we don't affect the caller's $PWD
    (cd .. && findconfig "$1")
  fi
}

Sample run, with the setup stolen copied and extended from Stephen Harris's answer:

$ mkdir -p ~/tmp/iconoclast
$ cd ~/tmp/iconoclast
$ mkdir -p A/B/C/D/E/F A/good/show 
$ touch A/good/show/this A/B/C/D/E/F/srchup A/B/C/thefile 
$ cd A/B/C/D/E/F
$ findconfig thefile
/home/jeff/tmp/iconoclast/A/B/C/thefile
$ echo "$?"
0
$ findconfig foobar
$ echo "$?"
1
Related Question