is there an 'upwards' find?
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.
Related videos on Youtube
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, 2022Comments
-
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 almost 12 yearsIt appears from the link that you already wrote a script that solved your problem...
-
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 almost 12 yearsAh. Actually, I would think the best forum would be SO, wouldn't it?
-
Ciro Santilli Путлер Капут 六四事 about 9 yearsPossible same on unix SE: unix.stackexchange.com/questions/6463/…
-
WoodrowShigeru almost 3 yearsWithout having tested it, doesn't this print an incrementally growing result list with duplicates because the loop terminates when root is reached?
-
choroba almost 3 yearsWhy the loop termination at the root should result in duplicates?
-
WoodrowShigeru almost 3 yearsHm 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 runsfind
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.