zgrep: handle "-f -" the same way that it works with grep
[debian/gzip] / zgrep.in
1 #!/bin/sh
2
3 # zgrep -- a wrapper around a grep program that decompresses files as needed
4 # Adapted from a version sent by Charles Levert <charles@comm.polymtl.ca>
5
6 # Copyright (C) 1998, 2001, 2002, 2006, 2007, 2009 Free Software Foundation
7 # Copyright (C) 1993 Jean-loup Gailly
8
9 # This program is free software; you can redistribute it and/or modify
10 # it under the terms of the GNU General Public License as published by
11 # the Free Software Foundation; either version 3 of the License, or
12 # (at your option) any later version.
13
14 # This program is distributed in the hope that it will be useful,
15 # but WITHOUT ANY WARRANTY; without even the implied warranty of
16 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 # GNU General Public License for more details.
18
19 # You should have received a copy of the GNU General Public License along
20 # with this program; if not, write to the Free Software Foundation, Inc.,
21 # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22
23 bindir=@bindir@
24 case $1 in
25 --__bindir) bindir=${2?}; shift; shift;;
26 esac
27 PATH=$bindir:$PATH
28
29 grep='${GREP-grep}'
30
31 version='zgrep (gzip) @VERSION@
32 Copyright (C) 2007, 2009 Free Software Foundation, Inc.
33 This is free software.  You may redistribute copies of it under the terms of
34 the GNU General Public License <http://www.gnu.org/licenses/gpl.html>.
35 There is NO WARRANTY, to the extent permitted by law.
36
37 Written by Jean-loup Gailly.'
38
39 usage="Usage: $0 [OPTION]... [-e] PATTERN [FILE]...
40 Look for instances of PATTERN in the input FILEs, using their
41 uncompressed contents if they are compressed.
42
43 OPTIONs are the same as for 'grep'.
44
45 Report bugs to <bug-gzip@gnu.org>."
46
47 # sed script to escape all ' for the shell, and then (to handle trailing
48 # newlines correctly) turn trailing X on last line into '.
49 escape='
50   s/'\''/'\''\\'\'''\''/g
51   $s/X$/'\''/
52 '
53 operands=
54 have_pat=0
55 pat_on_stdin=0
56 files_with_matches=0
57 files_without_matches=0
58 no_filename=0
59 with_filename=0
60
61 while test $# -ne 0; do
62   option=$1
63   shift
64   optarg=
65
66   case $option in
67   (-[0123456789abcdhHiIKLlnoqrRsTuUvVwxyzZ]?*)
68     arg2=-\'$(expr "X${option}X" : 'X-.[0-9]*\(.*\)' | sed "$escape")
69     eval "set -- $arg2 "'${1+"$@"}'
70     option=$(expr "X$option" : 'X\(-.[0-9]*\)');;
71   (--binary-*=* | --[lm]a*=* | --reg*=*)
72     ;;
73   (-[ABCDefm] | --binary-* | --file | --[lm]a* | --reg*)
74     case ${1?"$option option requires an argument"} in
75     (*\'*)
76       optarg=" '"$(printf '%sX\n' "$1" | sed "$escape");;
77     (*)
78       optarg=" '$1'";;
79     esac
80     shift;;
81   (--)
82     break;;
83   (-?*)
84     ;;
85   (*)
86     case $option in
87     (*\'*)
88       operands="$operands '"$(printf '%sX\n' "$option" | sed "$escape");;
89     (*)
90       operands="$operands '$option'";;
91     esac
92     ${POSIXLY_CORRECT+break}
93     continue;;
94   esac
95
96   case $option in
97   (-[drRzZ] | --di* | --exc* | --inc* | --rec* | --nu*)
98     printf >&2 '%s: %s: option not supported\n' "$0" "$option"
99     exit 2;;
100   (-[ef]* | --file | --file=* | --reg*)
101     # The pattern is coming from a file rather than the command-line.
102     # If the file is actually stdin then we need to do a little
103     # magic, (since we use stdin to pass the gzip output to grep).
104     # So find a free fd and change the argument to then use this
105     # file descriptor for the pattern.
106     case $optarg in
107     (" '-'" | " '/dev/stdin'" | " '/dev/fd/0'")
108       pat_on_stdin=1
109       # Start search from 6 since the script already uses 3 and 5
110       for fd in $(seq 6 254); do
111         if test ! -e /dev/fd/$fd; then
112           pat_fd=$fd
113           break;
114         fi
115       done
116       optarg=/dev/fd/$pat_fd;
117     esac
118     have_pat=1;;
119   (--h | --he | --hel | --help)
120     echo "$usage" || exit 2
121     exit;;
122   (-H | --wi | --wit | --with | --with- | --with-f | --with-fi \
123   | --with-fil | --with-file | --with-filen | --with-filena | --with-filenam \
124   | --with-filename)
125     with_filename=1
126     continue;;
127   (-l | --files-with-*)
128     files_with_matches=1;;
129   (-L | --files-witho*)
130     files_without_matches=1;;
131   (--no-f*)
132     no_filename=1;;
133   (-V | --v | --ve | --ver | --vers | --versi | --versio | --version)
134     echo "$version" || exit 2
135     exit;;
136   esac
137
138   case $option in
139   (*\'?*)
140     option=\'$(expr "X${option}X" : 'X\(.*\)' | sed "$escape");;
141   (*)
142     option="'$option'";;
143   esac
144
145   grep="$grep $option$optarg"
146 done
147
148 eval "set -- $operands "'${1+"$@"}'
149
150 if test $have_pat -eq 0; then
151   case ${1?"missing pattern; try \`$0 --help' for help"} in
152   (*\'*)
153     grep="$grep -- '"$(printf '%sX\n' "$1" | sed "$escape");;
154   (*)
155     grep="$grep -- '$1'";;
156   esac
157   shift
158 fi
159
160 if test $# -eq 0; then
161   set -- -
162 fi
163
164 exec 3>&1
165 res=0
166
167 for i
168 do
169   # Fail if gzip or grep (or sed) fails.
170   gzip_status=$(
171     exec 5>&1
172     if test $pat_on_stdin -eq 1; then
173       eval "exec $pat_fd<&0"
174     fi
175     (gzip -cdfq -- "$i" 5>&-; echo $? >&5) 3>&- |
176     if test $files_with_matches -eq 1; then
177       eval "$grep" >/dev/null && { printf '%s\n' "$i" || exit 2; }
178     elif test $files_without_matches -eq 1; then
179       eval "$grep" >/dev/null || {
180         r=$?
181         if test $r -eq 1; then
182           printf '%s\n' "$i" || r=2
183         fi
184         exit $r
185       }
186     elif test $with_filename -eq 0 &&
187          { test $# -eq 1 || test $no_filename -eq 1; }; then
188       eval "$grep"
189     else
190       case $i in
191       (*'
192 '* | *'&'* | *'\'* | *'|'*)
193         i=$(printf '%s\n' "$i" |
194             sed '
195               $!N
196               $s/[&\|]/\\&/g
197               $s/\n/\\n/g
198             ');;
199       esac
200       sed_script="s|^|$i:|"
201
202       # Fail if grep or sed fails.
203       r=$(
204         exec 4>&1
205         (eval "$grep" 4>&-; echo $? >&4) 3>&- | sed "$sed_script" >&3 4>&-
206       ) || r=2
207       exit $r
208     fi >&3 5>&-
209   )
210   r=$?
211   test "$gzip_status" -eq 0 || test "$gzip_status" -eq 2 || r=2
212   test $res -lt $r && res=$r
213 done
214 exit $res