I am trying to look for a certain file in multiple folders. When I hit the file, I want to stop going to sub-directory. For example:
/foo/.target
/bar/buz/.target
/foo/bar/.target
I want only the first two:
/foo/.target
/bar/buz/.target
I am trying to look for a certain file in multiple folders. When I hit the file, I want to stop going to sub-directory. For example:
/foo/.target
/bar/buz/.target
/foo/bar/.target
I want only the first two:
/foo/.target
/bar/buz/.target
Your requirements are not completely clear. I understand them as: look for “wanted” files inside a directory tree; if a directory directly contains at least one match, then just print them, otherwise recurse into that directory.
I can't think of a pure find solution. You could write an awk or perl script to parse the output of find.
Here's a shell script that I think does what you're looking for. Warning: I've only minimally tested it.
#!/bin/sh
## Return 0 if $1 is a matching file, 1 otherwise.
## Note that $1 is the full path to the file.
wanted () {
case ${1##*/} in
.target) true;;
esac
}
## Recurse into the directory $1. Print all wanted files in this directory.
## If there is no wanted file, recurse into each subdirectory in turn.
traverse () {
found=0
for x in "$1"/.* "$1"/*; do
if [ "$x" = "$1/." ] || [ "$x" = "$1/.." ]; then
continue # skip '.' and '..' entries
fi
if ! [ -e "$x" ]; then
continue # skip spurious '.*', '*' from non-matching patterns
fi
if wanted "$x"; then
printf '%s\n' "$x"
found=$(($found+1))
fi
done
if [ $found -eq 0 ]; then # no match here, so recurse
for x in "$1"/.*/ "$1"/*/; do
x=${x%/}
if [ "$x" = "$1/." ] || [ "$x" = "$1/.." ]; then
continue
fi
if [ -d "$x" ]; then # only actual subdirs, not symlinks or '.*' or '*'
found_stack=$found:$found_stack # no lexical scoping in sh
traverse "${x%/}"
found=${found_stack%%:*}
found_stack=${found_stack#*:}
fi
done
fi
}
found_stack=:
for x; do
if wanted "$x"; then
printf '%s\n' "$x"
else
traverse "$x"
fi
done