Here's a dash (also tested on bash, zsh, ksh shells) script that can search inside: .zip, .bz2, .xz, .tar.*, .tgz, .tar, .gz archives:
In order to run it: run it with no parameters and it will ask for the necessary info (reads input from keyboard):
#!/bin/dash
PrintInTitle () {
printf "\033]0;%s\007" "$1"
}
PrintJustInTitle () {
PrintInTitle "$1">"$print_to_screen"
}
CleanUp () {
trap - INT
trap - TSTP
if [ -n "$TEP" ] && [ -n "$TEF" ]; then
rm -R -f "$output_dir/"*
fi
unset IFS
PrintJustInTitle ""
if [ "$1" = "1" ]; then
printf "Aborted\n">"$print_to_screen"
kill -s PIPE -- -$$ 2>/dev/null
fi
}
StoreArchiveFilePath () {
eval k=$(($k + 1))
eval archive_files_$k=\"\$archive_file\"
}
PrintMatch () {
printf '\n%s\n\n' "$search_path$current_archive_file/$inside_current_archive_file"|grep --color -F "$search_path$current_archive_file/$inside_current_archive_file"
for i in $(seq 1 $search_strings_0); do
eval current_search_string=\"\$search_strings_$i\"
printf '\n%s\n\n' "$current_search_string:"|grep --color -F "$current_search_string:"
cat "$inside_current_archive_file"|grep -i -n -F "$current_search_string" 2>/dev/null
done
}
GetCurrentContent () {
cd "$TEP" && {
eval current_archive_file=\"\$$2\"
case "$current_archive_file" in
*'.zip' )
unzip "$full_search_path/""$current_archive_file" -d "$TEF" >/dev/null 2>/dev/null
;;
*'.bz2' )
bzip2 "$full_search_path/""$current_archive_file" -d "$TEF" >/dev/null 2>/dev/null
;;
*'.xz' )
xz "$full_search_path/""$current_archive_file" -d "$TEF" >/dev/null 2>/dev/null
;;
*'.tar.'* | *'.tgz' | *'.tar' )
tar -xvf "$full_search_path/""$current_archive_file" -C "$TEF" >/dev/null 2>/dev/null
;;
*'.gz' )
cp "$full_search_path/""$current_archive_file" "./$TEF"; gzip -d "./$TEF/""$current_archive_file" >/dev/null 2>/dev/null
;;
esac
cd "$output_dir"
for inside_current_archive_file in $(for t in $(seq 1 $inside_archive_file_path_filters_0); do eval current_inside_archive_file_path_filter=\"\$inside_archive_file_path_filters_$t\"; eval find . -type f -path "$current_inside_archive_file_path_filter"|sort --numeric-sort; done;); do
gcc_found="true"
for i in $(seq 1 $search_strings_0); do
eval current_search_string=\"\$search_strings_$i\"
gcc_stored_content="$(cat "$inside_current_archive_file"|grep -i -n -F "$current_search_string" 2>/dev/null;)";
if [ -z "$gcc_stored_content" ]; then
gcc_found="false"
break
fi
done
if [ "$gcc_found" = "true" ]; then
if [ "$1" = "StoreArchiveFilePath" ]; then
StoreArchiveFilePath
break
elif [ "$1" = "PrintMatch" ]; then
PrintMatch
fi
fi
done
if [ -n "$TEP" ] && [ -n "$TEF" ]; then rm -R -f "$output_dir/"*; fi
cd "$full_search_path"
}
}
set +f #Enable globbing (POSIX compliant)
setopt no_nomatch 2>/dev/null #Enable globbing (zsh)
IFS='
'
print_to_screen='/dev/tty'
initial_dir="$PWD"
case "$(uname -s)" in
*"Linux"* )
TEP='/dev/shm' #TEMPORARY_EXTRACT_PATH
;;
*"Darwin"* | *"BSD"* | * )
TEP="$HOME" #TEMPORARY_EXTRACT_PATH
;;
esac
TEF='TEMP_EXTRACT_FOLDER' #TEMP_EXTRACT_FOLDER
output_dir=""
error="false"
{
cd "$TEP" && {
if [ ! -e "$TEF" ]; then
printf '%s\n' "The specified temporary directory: \"$TEF\" - does not exist in the specified location: \"$TEP\" - do you want to create it? [ Yes / No ] (default=Enter=No): ">"$print_to_screen"
read answer
if [ "$answer" = "Yes" ] || [ "$answer" = "yes" ] || [ "$answer" = "Y" ] || [ "$answer" = "y" ]; then
mkdir "$TEF" || error="true"
fi
fi
cd "$TEF" && output_dir="$PWD" || error="true"
} || error="true"
} 2>/dev/null
if [ "$error" = "true" ]; then
printf '%s\n' "Error: Could not access temporary folder \"$TEF\" in the extract location: \"$TEP\"!">&2
read temp
exit 1
fi
trap 'CleanUp 1' INT
trap 'CleanUp 1' TSTP
cd "$HOME"
printf '%s\n' "Search Path (blank=default=current folder=$PWD): "
read search_path
if [ -z "$search_path" ]; then
search_path="."
fi
printf '\n%s\n' "Inside archive file path filters: (what file path to lookup inside the archive) (concatenated internaly with logical OR) (default=Enter='*'): ">"$print_to_screen"
i=0
while [ "1" = "1" ]; do
printf '%s' ">> inside archive path filter: >> "
IFS= read -r current_inside_archive_file_path_filter
unset IFS
if [ -z "$current_inside_archive_file_path_filter" ]; then
break
fi
i=$(($i + 1))
eval inside_archive_file_path_filters_$i=\"\$current_inside_archive_file_path_filter\"
done
inside_archive_file_path_filters_0=$i
unset IFS #Reset IFS
if [ "$inside_archive_file_path_filters_0" = "0" ]; then
inside_archive_file_path_filters_1="'"'*'"'"
inside_archive_file_path_filters_0="1"
fi
printf '\n%s\n' "Search strings (concatenated internaly with logical AND):">"$print_to_screen";
i=0
while [ "1" = "1" ]; do
printf '%s' ">> add search string: >> "
IFS= read -r current_search_string
unset IFS
if [ -z "$current_search_string" ]; then break; fi;
i=$(($i + 1))
eval search_strings_$i=\"\$current_search_string\"
done
search_strings_0=$i
if [ "$search_strings_0" = "0" ]; then
search_strings_1=""
search_strings_0=1
fi
i=0
PrintJustInTitle "Loading list of archive files to analyze..."
IFS='
'
cd "$search_path" && {
full_search_path="$PWD"
{ find . \( -type f -path '*.zip' -o -path '*.bz2' -o -path '*.xz' -o -path '*.tar.*' -o -path '*.tgz' -o -path '*.tar' -o -path '*.gz' \) -exec printf "%s\n" "{}" \;|sort --numeric-sort;\
printf '%s\n' "..."; index=defined; while [ -n "$index" ]; do read index; printf '%s\n' $index; done; }|{
j=0; k=0
while read -r line; do
j=$(($j + 1))
if [ "$line" = "..." ]; then
break
else
PrintJustInTitle "Analyzing archive file $j..."
archive_file="$line"
fi
GetCurrentContent StoreArchiveFilePath archive_file
done
archive_files_0="$k"
PrintJustInTitle ""
if [ ! "$k" = "0" ]; then
index="defined"
count="$archive_files_0"
while [ -n "$index" ]; do
for i in $(seq 1 $count); do
eval current_archive_file=\"\$archive_files_$i\"
printf '\033[0;31m%s\033[0m\n' "$i = ""$current_archive_file"
done
printf '\n%s\n' "Print results (one at a time - blank = exit)?: [ 1 - $count ]: "
read index
if [ -z "$index" ]; then
break
fi
printf '%s\n' '---------------------------------------------------------------'
GetCurrentContent PrintMatch archive_files_$index
printf '%s\n\n' '---------------------------------------------------------------'
done
fi
}
}
PrintJustInTitle ""
CleanUp
It consumes a lot of resources but the output is detailed.