The Android Open Source Project | b6c1cf6 | 2008-10-21 07:00:00 -0700 | [diff] [blame] | 1 | #!/bin/bash |
| 2 | # |
| 3 | # Copyright (C) 2008 The Android Open Source Project |
| 4 | # |
| 5 | # Licensed under the Apache License, Version 2.0 (the "License"); |
| 6 | # you may not use this file except in compliance with the License. |
| 7 | # You may obtain a copy of the License at |
| 8 | # |
| 9 | # http://www.apache.org/licenses/LICENSE-2.0 |
| 10 | # |
| 11 | # Unless required by applicable law or agreed to in writing, software |
| 12 | # distributed under the License is distributed on an "AS IS" BASIS, |
| 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 14 | # See the License for the specific language governing permissions and |
| 15 | # limitations under the License. |
| 16 | # |
| 17 | |
| 18 | # |
| 19 | # Finds files with the specified name under a particular directory, stopping |
| 20 | # the search in a given subdirectory when the file is found. |
| 21 | # |
| 22 | |
| 23 | set -o nounset # fail when dereferencing unset variables |
| 24 | set -o errexit # fail if any subcommand fails |
| 25 | |
| 26 | progName=`basename $0` |
| 27 | |
| 28 | function warn() { |
| 29 | echo "$progName: $@" >&2 |
| 30 | } |
| 31 | |
| 32 | function trace() { |
| 33 | echo "$progName: $@" |
| 34 | } |
| 35 | |
| 36 | function usage() { |
| 37 | if [[ $# > 0 ]] |
| 38 | then |
| 39 | warn $@ |
| 40 | fi |
| 41 | cat <<-EOF |
| 42 | Usage: $progName [<options>] <dirlist> <filename> |
| 43 | Options: |
| 44 | --mindepth=<mindepth> |
| 45 | --maxdepth=<maxdepth> |
| 46 | Both behave in the same way as their find(1) equivalents. |
| 47 | --prune=<glob> |
| 48 | Avoids returning results from any path matching the given glob-style |
| 49 | pattern (e.g., "*/out/*"). May be used multiple times. |
| 50 | EOF |
| 51 | exit 1 |
| 52 | } |
| 53 | |
| 54 | function fail() { |
| 55 | warn $@ |
| 56 | exit 1 |
| 57 | } |
| 58 | |
| 59 | if [ $# -lt 2 ] |
| 60 | then |
| 61 | usage |
| 62 | fi |
| 63 | |
| 64 | findargs="" |
| 65 | while [[ "${1:0:2}" == "--" ]] |
| 66 | do |
| 67 | arg=${1:2} |
| 68 | name=${arg%%=*} |
| 69 | value=${arg##*=} |
| 70 | if [[ "$name" == "mindepth" || "$name" == "maxdepth" ]] |
| 71 | then |
| 72 | # Add to beginning of findargs; these must come before the expression. |
| 73 | findargs="-$name $value $findargs" |
| 74 | elif [[ "$name" == "prune" ]] |
| 75 | then |
| 76 | # Add to end of findargs; these are part of the expression. |
| 77 | findargs="$findargs -path $value -prune -or" |
| 78 | fi |
| 79 | shift |
| 80 | done |
| 81 | |
| 82 | nargs=$# |
| 83 | # The filename is the last argument |
| 84 | filename="${!nargs}" |
| 85 | |
| 86 | # Print out all files that match, as long as the path isn't explicitly |
| 87 | # pruned. This will print out extraneous results from directories whose |
| 88 | # parents have a match. These are filtered out by the awk script below. |
Sean McNeil | 19ea2a8 | 2009-04-03 08:55:18 +0700 | [diff] [blame] | 89 | find -L "${@:1:$nargs-1}" $findargs -type f -name "$filename" -print 2>/dev/null | |
The Android Open Source Project | b6c1cf6 | 2008-10-21 07:00:00 -0700 | [diff] [blame] | 90 | |
| 91 | # Only pass along the directory of each match. |
| 92 | sed -e 's/\/[^\/]*$/\//' | |
| 93 | |
| 94 | # Sort the output, so directories appear immediately before their contents. |
| 95 | # If there are any duplicates, the awk script will implicitly ignore them. |
The Android Open Source Project | dcc08f0 | 2008-12-17 18:03:49 -0800 | [diff] [blame] | 96 | # The LC_ALL=C forces sort(1) to use bytewise ordering instead of listening |
| 97 | # to the locale, which may do case-insensitive and/or alphanumeric-only |
| 98 | # sorting. |
| 99 | LC_ALL=C sort | |
The Android Open Source Project | b6c1cf6 | 2008-10-21 07:00:00 -0700 | [diff] [blame] | 100 | |
| 101 | # Always print the first line, which can't possibly be covered by a |
| 102 | # parent directory match. After that, only print lines where the last |
| 103 | # line printed isn't a prefix. |
| 104 | awk -v "filename=$filename" ' |
| 105 | (NR == 1) || (index($0, last) != 1) { |
| 106 | last = $0; |
| 107 | printf("%s%s\n", $0, filename); |
| 108 | } |
| 109 | ' |