zipgrep 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. #!/bin/sh
  2. #
  3. # zipgrep: Use unzip and egrep to search the specified members of a
  4. # Zip archive for a string or pattern. Search all members if no members
  5. # are specified explicitly. The script attempts to handle egrep's "-h"
  6. # and "-l" options internally.
  7. #
  8. # This script assumes that the desired "unzip" and "egrep" (and "sed")
  9. # programs are on the user's PATH.
  10. #
  11. pat=""
  12. opt=""
  13. while test $# -ne 0; do
  14. case "$1" in
  15. -e | -f) opt="$opt $1"; shift; pat="$1";;
  16. -*) opt="$opt $1";;
  17. *) if test -z "$pat"; then
  18. pat="$1"
  19. else
  20. break;
  21. fi;;
  22. esac
  23. shift
  24. done
  25. if test $# = 0; then
  26. echo usage: `basename "$0"` "[egrep_options] pattern zipfile [members...]"
  27. echo Uses unzip and egrep to search the zip members for a string or pattern.
  28. exit 1
  29. fi
  30. zipfile="$1"; shift
  31. list=0
  32. silent=0
  33. opt=`echo "$opt" | sed -e 's/ //g' -e 's/-//g'`
  34. case "$opt" in
  35. *l*) list=1; opt=`echo $opt | sed s/l//`
  36. esac
  37. case "$opt" in
  38. *h*) silent=1
  39. esac
  40. if test -n "$opt"; then
  41. opt="-$opt"
  42. fi
  43. status_grep_global=1
  44. IFS='
  45. '
  46. # Escape shell-special characters in "pat".
  47. pat=` echo "$pat" | \
  48. sed -e 's/\\\\/\\\\\\\\/g' -e 's/|/\\\|/g' -e 's/&/\\\&/g' `
  49. # Use "unzip -Z1" to get a listing of the specified members from the
  50. # specified archive. Escape any backslashes in a file name.
  51. for i in `unzip -Z1 "$zipfile" ${1+"$@"} | sed -e 's/\\\\/\\\\\\\\/g' `; do
  52. if test $list -eq 1; then
  53. # "-l": Show only the archive member name, not the matching line(s).
  54. unzip -p-L "$zipfile" "$i" | \
  55. egrep $opt "$pat" > /dev/null && echo "$i"
  56. status_grep=$?
  57. elif test $silent -eq 1; then
  58. # "-h": Show only the matching line(s), not the archive member name.
  59. # ("-s" in "opt" will silence "egrep", stopping all output.)
  60. unzip -p-L "$zipfile" "$i" | \
  61. egrep $opt "$pat"
  62. status_grep=$?
  63. else
  64. # Escape (or re-escape) shell-special characters in the archive
  65. # member name, "i".
  66. i=` echo "$i" | \
  67. sed -e 's/\\\\/\\\\\\\\/g' -e 's/|/\\\|/g' -e 's/&/\\\&/g' `
  68. # Globally, send fd 4 to stdout. In the pipeline, send normal
  69. # stdout to fd 4, and send grep status to fd 3. Collect fd 3
  70. # with ``.
  71. exec 4>&1
  72. status_grep=` ( \
  73. ( unzip -p-L "$zipfile" "$i" | \
  74. egrep $opt "$pat" 1>&4 ; echo $? >&3 ) 4>&1 | \
  75. sed "s|^|${i}:|" 1>&4 \
  76. ) 3>&1 `
  77. fi
  78. # Save the primary command status. (May be the grep status.)
  79. sts=$?
  80. # If this grep status was zero, set the global grep status to zero.
  81. test "$status_grep" -eq 0 && status_grep_global=0
  82. # If this grep status was not zero or one, exit now.
  83. test "$status_grep" -gt 1 && exit "$status_grep"
  84. done
  85. # If "sts" is good (0), then exit with the global grep status.
  86. # Else, when "sts" is bad, exit with the worst status we can find.
  87. if test $sts -eq 0 ; then
  88. exit $status_grep_global
  89. else
  90. if test "$status_grep" -gt 1 ; then
  91. exit "$status_grep"
  92. else
  93. exit $sts
  94. fi
  95. fi