is there an 'upwards' find?

5,510

Solution 1

You can use this simple script. It walks the directory tree upwards and searches for the specified files.

#!/bin/bash
while [[ $PWD != / ]] ; do
    find "$PWD"/ -maxdepth 1 "$@"
    cd ..
done

Usage:

upfind -name 'x*'

Solution 2

You can just split the path into its constituent directory nodes and search each one discreetly. It is a bash script.

IFS=/; dn=($1); ct=${#dn[@]}
for((i=0; i<ct; i++)); do
  subd+=/"${dn[i]}"
  dots=$(for((j=ct-i; j>1; j--)); do printf "../"; done)
  find "$subd" -maxdepth 1 -type f -name "$2" -printf "$dots%f\n"
done

run upfind $HOME/zt" "Y*" ... which produces the following output
when YABBA exists in /, /home/user, /home/user/zt

../../../YABBA
../YABBA
YABBA

Solution 3

Expanding on @choroba's answer with my own solution for finding the upward location of a file (by name):

upfind() {
  ORIG_DIR="$PWD"
  while [[ "$PWD" != / ]] ; do
    if find "$PWD"/ -maxdepth 1 -type f -name "$@" | grep -q "$@"; then
      echo "$PWD" && builtin cd "$ORIG_DIR"
      return 0
    else
      builtin cd ..
    fi
  done
  builtin cd "$ORIG_DIR"
  return 1
}

Example:

> upfind packageInfo
/home/matthew/development/packageRoot

It will return with an error code, which is useful if you're using it in a conditional. However, this solution is less of an upward version of find (I assume it won't play nice when you pass in additional parameters) as it is a specific solution to finding a file by name.

Share:
5,510

Related videos on Youtube

xtofl
Author by

xtofl

Love a clean program, where you can tell each functions meaning, each class's responsibilities, each variable's purpose. Balancing between getting that right, and getting the job done.

Updated on September 18, 2022

Comments

  • xtofl
    xtofl over 1 year

    I found I asked this question on the wrong stackexchange site.

    To find files starting from a certain path, I can use find <path> .... If I want to find 'upwards', i.e. in the parent directory, and it's parent, and..., is there an equivalent tool?

    The use case is knowing the right number of dots (../../x.txt or ../../../x.txt?) to use in e.g. a makefile including some common makefile functions somewhere upstream.

    Intended usage for a folder structure like this:

    /
    /abc
    /abc/dce/efg/ghi
    /abc/dce/efg2
    
    
    $ cd /abc/dce/efg/ghi
    $ touch ../../x.txt
    $ upfind . -name X*
    ../../x.txt
    $ upfind . -name Y* || echo "not found"
    not found
    $ touch /abc/dce/efg2/x.txt
    $ upfind . -name Y* || echo "not found"
    not found
    $ 
    

    So in short:

    • it should search on this folder, it's parent, it's parent's parent...
    • but not in any of their siblings (like 'find' would)
    • it should report the found file(s) relative to the current path
    • Lsds9
      Lsds9 almost 12 years
      It appears from the link that you already wrote a script that solved your problem...
    • xtofl
      xtofl almost 12 years
      @Matt: yes, but I'm allways try to find one better answer, and this is a better forum to do so.
    • Lsds9
      Lsds9 almost 12 years
      Ah. Actually, I would think the best forum would be SO, wouldn't it?
    • Ciro Santilli Путлер Капут 六四事
      Ciro Santilli Путлер Капут 六四事 about 9 years
      Possible same on unix SE: unix.stackexchange.com/questions/6463/…
  • WoodrowShigeru
    WoodrowShigeru almost 3 years
    Without having tested it, doesn't this print an incrementally growing result list with duplicates because the loop terminates when root is reached?
  • choroba
    choroba almost 3 years
    Why the loop termination at the root should result in duplicates?
  • WoodrowShigeru
    WoodrowShigeru almost 3 years
    Hm okay: I was wrong with the duplicates because I didn't consider the -maxdepth flag when I said that. I was also under the impression that we want to stop searching after the first match, and this script doesn't do that – it runs find on each iteration until we reach the root. I treated this problem more like .closest() in jQuery. But no, upfind should behave like you suggested. Never mind me.