blob: 7cc0fa77597fe1a8198e7ec06d3349c9b2c4e364 [file] [log] [blame]
The Android Open Source Project88b60792009-03-03 19:28:42 -08001#!/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
23set -o nounset # fail when dereferencing unset variables
24set -o errexit # fail if any subcommand fails
25
26progName=`basename $0`
27
28function warn() {
29 echo "$progName: $@" >&2
30}
31
32function trace() {
33 echo "$progName: $@"
34}
35
36function usage() {
37 if [[ $# > 0 ]]
38 then
39 warn $@
40 fi
41 cat <<-EOF
42Usage: $progName [<options>] <dirlist> <filename>
43Options:
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.
50EOF
51 exit 1
52}
53
54function fail() {
55 warn $@
56 exit 1
57}
58
59if [ $# -lt 2 ]
60then
61 usage
62fi
63
64findargs=""
65while [[ "${1:0:2}" == "--" ]]
66do
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
80done
81
82nargs=$#
83# The filename is the last argument
84filename="${!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.
89find "${@:0:$nargs}" $findargs -type f -name "$filename" -print |
90
91# Only pass along the directory of each match.
92sed -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.
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.
99LC_ALL=C sort |
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.
104awk -v "filename=$filename" '
105 (NR == 1) || (index($0, last) != 1) {
106 last = $0;
107 printf("%s%s\n", $0, filename);
108 }
109'