2

I have a large directory tree of builds. Standard find search locates the file after a minute or two. I'd like it to be in a few seconds.

I need to find a file named foo.tar.gz. The file can reside in various directories:

/mnt/build/my_project/master/<BUILD_NAME>/foo.tar.gz
/mnt/build/my_project/master/<BUILD_NAME>/<PREFIX>/foo.tar.gz
/mnt/build/my_project/main/<BRANCH>/<BUILD_NAME>/foo.tar.gz
/mnt/build/my_project/main/<BRANCH>/<BUILD_NAME>/PREFIX>/foo.tar.gz
/mnt/build/my_project/side/<BUILD_NAME>/foo.tar.gz
/mnt/build/my_project/side/<BUILD_NAME>/<PREFIX>/foo.tar.gz

I've tried numerous if [[ -f .. ]] statements, which do reduce the script runtime, but there are too many cases to cover and maintaining the script is becoming a hassle.

I've also tried these find statements:

find /mnt/build/my_project/ -ipath "*${BUILD_NAME}*" -name foo.tar.gz -type f
find /mnt/build/my_project/ -wholename "*${BUILD_NAME}*/foo.tar.gz" -type f

How can I efficiently search all this directory tree if a user provides a BUILD_NAME ?

Thanks!

1

If you just run find, it has to go through all the subdirectories to find all the files. It looks like you expect the file to be at a low depth, so you could pass the -maxdepth argument to limit the depth of the search, e.g.

find /mnt/build/my_project/ -maxdepth 3 -wholename "*${BUILD_NAME}*/foo.tar.gz" -type f

Alternatively, you could skip find altogether and make your shell do the lookup. Assuming that your shell is bash (this can be adjusted for ksh or zsh):

shopt -s nullglob
candidates=(
  /mnt/build/my_project/*/"$BUILD_NAME"/*/foo.tar.gz
  /mnt/build/my_project/*/"$BUILD_NAME"/*/foo.tar.gz
  /mnt/build/my_project/*/*/"$BUILD_NAME"/*/foo.tar.gz
  /mnt/build/my_project/*/*/"$BUILD_NAME"/*/*/foo.tar.gz
)
case "${#candidates[@]}" in
  0) echo "No foo.tar.gz found";;
  1) echo "Got foo.tar.gz in ${candidates[0]}"
  *) echo "I don't know which foo.tar.gz to pick among" "${candidates[@]}";;
esac

If you can't limit the depth of search, there's no obvious way to prune parts of the tree. Maybe you can skip some subdirectories that you know aren't useful, e.g. to skip all .svn directories:

find /mnt/build/my_project/ -name .svn -prune -o -wholename "*${BUILD_NAME}*/foo.tar.gz" -type f -print

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.