codekingpro/portable-devtools
114k
1#!/bin/sh2 3# zgrep -- a wrapper around a grep program that decompresses files as needed4# Adapted from a version sent by Charles Levert <charles@comm.polymtl.ca>5 6# Copyright (C) 1998, 2001-2002, 2006-2007, 2009-2025 Free Software Foundation,7# Inc.8 9# Copyright (C) 1993 Jean-loup Gailly10 11# This program is free software; you can redistribute it and/or modify12# it under the terms of the GNU General Public License as published by13# the Free Software Foundation; either version 3 of the License, or14# (at your option) any later version.15 16# This program is distributed in the hope that it will be useful,17# but WITHOUT ANY WARRANTY; without even the implied warranty of18# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the19# GNU General Public License for more details.20 21# You should have received a copy of the GNU General Public License22# along with this program. If not, see <https://www.gnu.org/licenses/>.23 24grep='${GREP-'\''/usr/bin/grep'\''}'25args=26 27version='zgrep (gzip) 1.1428Copyright (C) 2025 Free Software Foundation, Inc.29This is free software. You may redistribute copies of it under the terms of30the GNU General Public License <https://www.gnu.org/licenses/gpl.html>.31There is NO WARRANTY, to the extent permitted by law.32 33Written by Jean-loup Gailly.'34 35usage="Usage: $0 [OPTION]... [-e] PATTERN [FILE]...36Look for instances of PATTERN in the input FILEs, using their37uncompressed contents if they are compressed.38 39OPTIONs are the same as for 'grep', except that the following 'grep'40options are not supported: --dereference-recursive (-R), --directories (-d),41--exclude, --exclude-from, --exclude-dir, --include, --null (-Z),42--null-data (-z), and --recursive (-r).43 44Report bugs to <bug-gzip@gnu.org>."45 46# sed script to escape all ' for the shell, and then (to handle trailing47# newlines correctly) append ' to the last line.48escape='49 s/'\''/'\''\\'\'''\''/g50 $s/$/'\''/51'52operands=53have_pat=054files_with_matches=055files_without_matches=056no_filename=057with_filename=058pattmp=59 60while test $# -ne 0; do61 option=$162 shift63 optarg=64 65 case $option in66 (-[0123456789EFGHIKLPRTUVZabchilnoqrsuvwxyz]*[!0123456789]*)67 arg2=-\'$(LC_ALL=C expr "X$option" : 'X-.[0-9]*\(.*\)' |68 LC_ALL=C sed "$escape")69 eval "set -- $arg2 "'${1+"$@"}'70 option=$(LC_ALL=C expr "X$option" : 'X\(-.[0-9]*\)');;71 (--binary-*=* | --[lm]a*=* | --reg*=*)72 ;;73 (-[ABCDXdefm] | --binary-* | --file | --[lm]a* | --reg*)74 case ${1?"$option option requires an argument"} in75 (*\'*)76 optarg=" '"$(printf '%s\n' "$1" | LC_ALL=C sed "$escape");;77 (*)78 optarg=" '$1'";;79 esac80 shift;;81 (-f?*\'*)82 optarg=" '"$(LC_ALL=C expr "X$option" : 'X-f\(.*\)' |83 LC_ALL=C sed "$escape")84 option=-f;;85 (-f?*)86 optarg=" '"$(LC_ALL=C expr "X$option" : 'X-f\(.*\)')\'87 option=-f;;88 (--file=*\'*)89 optarg=" '"$(LC_ALL=C expr "X$option" : 'X--file=\(.*\)' |90 LC_ALL=C sed "$escape")91 option=--file;;92 (--file=*)93 optarg=" '"$(LC_ALL=C expr "X$option" : 'X--file=\(.*\)')\'94 option=--file;;95 (--)96 break;;97 (-?*)98 ;;99 (*)100 case $option in101 (*\'*)102 operands="$operands '"$(printf '%s\n' "$option" | LC_ALL=C sed "$escape")103 ;;104 (*)105 operands="$operands '$option'";;106 esac107 ${POSIXLY_CORRECT+break}108 continue;;109 esac110 111 case $option in112 (-[drRzZ] | --di* | --exc* | --inc* | --rec* | --nu*)113 printf >&2 '%s: %s: option not supported\n' "$0" "$option"114 exit 2;;115 (-e* | --reg*)116 have_pat=1;;117 (-f | --file)118 # The pattern is coming from a file rather than the command-line.119 # If the file is actually stdin then we need to do a little120 # magic, since we use stdin to pass the gzip output to grep.121 # Similarly if it is not a regular file, since it might be read repeatedly.122 # In either of these two cases, copy the pattern into a temporary file,123 # and use that file instead. The pattern might contain null bytes,124 # so we cannot simply switch to -e here.125 if case $optarg in126 (" '-'" | " '/dev/stdin'" | " '/dev/fd/0'")127 :;;128 (*)129 eval "test ! -f$optarg";;130 esac131 then132 if test -n "$pattmp"; then133 eval "cat --$optarg" >>"$pattmp" || exit 2134 continue135 fi136 trap '137 test -n "$pattmp" && rm -f "$pattmp"138 (exit 2); exit 2139 ' HUP INT PIPE TERM 0140 case $TMPDIR in141 / | /*/) ;;142 /*) TMPDIR=$TMPDIR/;;143 *) TMPDIR=/tmp/;;144 esac145 if command -v mktemp >/dev/null 2>&1; then146 pattmp=$(mktemp "${TMPDIR}zgrepXXXXXXXXX") || exit 2147 else148 set -C149 pattmp=${TMPDIR}zgrep$$150 fi151 eval "cat --$optarg" >"$pattmp" || exit 2152 optarg=' "$pattmp"'153 fi154 have_pat=1;;155 (--h | --he | --hel | --help)156 printf '%s\n' "$usage" || exit 2157 exit;;158 (-H | --wi | --wit | --with | --with- | --with-f | --with-fi \159 | --with-fil | --with-file | --with-filen | --with-filena | --with-filenam \160 | --with-filename)161 with_filename=1162 continue;;163 (-l | --files-with-*)164 files_with_matches=1;;165 (-L | --files-witho*)166 files_without_matches=1;;167 (-h | --no-f*)168 no_filename=1;;169 (-V | --v | --ve | --ver | --vers | --versi | --versio | --version)170 printf '%s\n' "$version" || exit 2171 exit;;172 esac173 174 case $option in175 (*\'?*)176 option=\'$(printf '%s\n' "$option" | LC_ALL=C sed "$escape");;177 (*)178 option="'$option'";;179 esac180 181 args="$args $option$optarg"182done183 184eval "set -- $operands "'${1+"$@"}'185 186if test $have_pat -eq 0; then187 case ${1?"missing pattern; try \`$0 --help' for help"} in188 (*\'*)189 args="$args -- '"$(printf '%s\n' "$1" | LC_ALL=C sed "$escape");;190 (*)191 args="$args -- '$1'";;192 esac193 shift194fi195 196if test $# -eq 0; then197 set -- -198elif test 1 -lt $# && test $no_filename -eq 0; then199 with_filename=1200fi201 202l_e=$(eval "(echo e | $grep -H --label=l e) 2>/dev/null") && test "$l_e" = l:e203gnuish_grep="test $? -eq 0"204if $gnuish_grep && test $with_filename -eq 1; then205 grep="$grep -H"206fi207 208exec 3>&1209res=1210 211for i212do213 # Fail if gzip or grep (or sed) fails.214 gzip_status=$(215 exec 5>&1216 (gzip -cdfq -- "$i" 5>&-; echo $? >&5) 3>&- |217 if test $files_with_matches -eq 1; then218 eval "$grep$args" >/dev/null && { printf '%s\n' "$i" || exit 2; }219 elif test $files_without_matches -eq 1; then220 eval "$grep$args" >/dev/null || {221 r=$?222 if test $r -eq 1; then223 printf '%s\n' "$i" || r=2224 fi225 test 256 -le $r && r=$(expr 128 + $r % 128)226 exit $r227 }228 elif $gnuish_grep && test "$i" != -; then229 eval "$grep --label \"\$i\"$args"230 elif $gnuish_grep || test $with_filename -eq 0; then231 eval "$grep$args"232 else233 case $i in234 (*'235'* | *'&'* | *'\'* | *'|'*)236 icolon=$(printf '%s\n' "$i:" |237 LC_ALL=C sed -e 's/[&\|]/\\&/g' -e '$!s/$/\\/') ||238 icolon='(unknown filename):';;239 (*) icolon="$i:";;240 esac241 sed_script="s|^|$icolon|"242 243 # Fail if grep or sed fails.244 r=$(245 exec 4>&1246 (eval "$grep$args" 4>&-; echo $? >&4) 3>&- |247 LC_ALL=C sed "$sed_script" >&3 4>&-248 ) || { r=$?; test $r -lt 2 && r=2; }249 test 256 -le $r && r=$(expr 128 + $r % 128)250 exit $r251 fi >&3 5>&-252 )253 r=$?254 255 # Ignore gzip status 2 or 141, as it is just a warning or broken pipe.256 # gzip status 1 is an error, like grep status 2.257 { test $gzip_status -eq 2 || test $gzip_status -eq 141; } && gzip_status=0258 test $gzip_status -eq 1 && gzip_status=2259 260 # Use the more serious of the grep and gzip statuses.261 test $r -lt $gzip_status && r=$gzip_status262 263 # Accumulate the greatest status, except consider 0 to be greater than 1.264 if test $r -le 1 && test $res -le 1; then265 test $r -lt $res266 else267 test $res -lt $r268 fi && res=$r269 270 # Exit immediately on a serious error.271 test 126 -le $res && break272done273 274if test -n "$pattmp"; then275 rm -f "$pattmp" || {276 r=$?277 test $r -lt 2 && r=2278 test $res -lt $r && res=$r279 }280 trap - HUP INT PIPE TERM 0281fi282 283test 128 -le $res && kill -$(expr $res % 128) $$284exit $res285 