I have 348 zip files and I want to find a file that is in one of the zip files, unzip -l doesn't work with wild cards?
How can I list content of all .zip files and grep through the merged list of all files contained in the zips?
I have 348 zip files and I want to find a file that is in one of the zip files, unzip -l doesn't work with wild cards?
How can I list content of all .zip files and grep through the merged list of all files contained in the zips?
Using zipinfo is a fine solution here. However, in general whenever you want to apply a command to a list of files and the command doesn’t accept a list of files, you can use a for loop:
for file in *.zip; do
unzip -l "$file"
done \
| grep "\.zip\|setup"
If the file you are searching for has spaces in it like: your file, in the grep regular expression you need to escape every space with a backslash like grep "\.zip\|your\ file".
You can use zipinfo. It is included in the default Ubuntu installation. Check the manual page for more info.
For example, to look for a pattern setup in a bunch of zip files in current directory, use this command:
find ./ -iname *zip 2> /dev/null -print0 | xargs -0 zipinfo | grep setup
To list the files in a zip archive you can use the following command.
unzip -l
To grep a compressed archive you should use the compressed archive utilities built to work with that type of archive format.
For zip archives:
zipgrep --help
usage: zipgrep [egrep_options] pattern zipfile [members...]
Uses unzip and egrep to search the zip members for a string or pattern.
For tar archives:
zgrep --help
Usage: /bin/zgrep [OPTION]... [-e] PATTERN [FILE]...
Look for instances of PATTERN in the input FILEs, using their
uncompressed contents if they are compressed.
OPTIONs are the same as for 'grep'.
There are a few other tools that work with archives as well. You can pipe the out put into grep to do the same thing.
zcat
zcat my.archive.zip | grep "some text"
Or you can use the search functionality of these tools
zless
zmore
Here's a dash script for searching inside .zip files (should work with bash, zsh, ksh shells):
Simply call the script with no parameters and the script will prompt for necessary input:
search location (the location can be: a folder path parameter OR separate zip file paths parameters)path filters for files inside the zip filesstrings to search for inside the files in the zip files#!/bin/dash
ExtractFirstAndLastPathComponent () {
#$1 = input path
#$2 = returns the first path component
#$3 = returns the last path component
eval current_path="\"\$$1\""
first_path_component=""
last_path_component=""
if [ -n "$current_path" ]; then
#Remove trailing '/':
temp="${current_path%?}"
while [ "${current_path#"$temp"}" = "/" ]; do
current_path="${current_path%?}"
temp="${current_path%?}"
done
first_path_component="${current_path%"/"*}"
if [ -z "$first_path_component" ]; then
last_path_component="${current_path#'/'}"
else
last_path_component="${current_path#"$first_path_component""/"}"
fi
fi
eval $2="\"\$first_path_component\""
eval $3="\"\$last_path_component\""
}
GetFileEncoding () {
#$1 = input file path
#$2 = returns the file encoding
eval file_to_test=\"\$$1\"
GetFileSizeInBytes file_to_test file_to_test_size_in_bytes
#Get file mime encoding:
if [ -d "$file_to_test" ]; then
result="directory"
elif [ ! "$file_to_test_size_in_bytes" -eq "0" ]; then
file_mime_type="$(file -bL --mime-encoding "$file_to_test" 2>/dev/null)" || { file_mime_type="undetermined"; }
case "$file_mime_type" in
*"binary"* )
#Only binary files containing the NULL character (^@) are considered binaries in this script:
(cat -v "$file_to_test" | sed "/\^@/i'\^@'\$NL2") | { grep -q "\^@"; } && result="binary" || result="text"
;;
*"ascii"* | *"utf"* )
result="text"
;;
* )
result="undetermined"
;;
esac
else
result="text"
fi
eval $2=\"\$result\"
}
GetOSType () {
#$1 = returns current operating system
case "$(uname -s)" in
*"Darwin"* | *"BSD"* )
eval $1="BSD-based"
;;
*"Linux"* )
eval $1="Linux"
;;
* )
eval $1="Other"
;;
esac
}
GetFileSizeInBytes () {
#$1 = the input file path
#$2 = returns the input file size
eval file="\"\$$1\""
[ -z "$OS_TYPE" ] && GetOSType OS_TYPE
if [ "$OS_TYPE" = "Linux" ] || [ "$OS_TYPE" = "Other" ]; then
file_size_in_bytes="$(stat -c %s -- "$file")" 2>/dev/null || { file_size_in_bytes="-1"; }
elif [ "$OS_TYPE" = "BSD-based" ]; then
file_size_in_bytes="$(stat -Lf %z -- "$file")" 2>/dev/null || { file_size_in_bytes="-1"; }
else
file_size_in_bytes="-1"
fi
eval $2="$file_size_in_bytes"
}
trap1 () {
printf "\n""Aborted.\n">"$print_to_screen"
CleanUp
#kill all children processes, suppressing "Terminated" message:
kill -s PIPE -- -$$ 2>/dev/null
exit
}
CleanUp () {
if [ -n "$TEMPORARY_EXTRACT_PATH" ] && [ -n "$TEMPORARY_EXTRACT_FOLDER" ]; then
rm -R -f "$output_dir/"*
fi
#Restore "INTERRUPT" (CTRL-C) and "TERMINAL STOP" (CTRL-Z) signals:
trap - INT
trap - TSTP
#Clear the title:
printf "\033]0;%s\007" "">"$print_to_screen"
#Restore initial IFS:
unset IFS
}
GetModifiedFileDateFull () {
#$1 = the input file path
#$2 = returns input file modified date
eval input_file=\"\$$1\"
[ -z "$OS_TYPE" ] && GetOSType OS_TYPE
{
if [ "$OS_TYPE" = "Linux" ] || [ "$OS_TYPE" = "Other" ]; then
current_modified_date_full="$(stat -c "%y" "$input_file")" || { current_modified_date_full="-1"; }
elif [ "$OS_TYPE" = "BSD-based" ]; then
current_modified_date_full="$(stat -f "%Sm" "$input_file")" || { current_modified_date_full="-1"; }
fi
}||{
current_modified_date_full="-1"
}
eval $2=\"\$current_modified_date_full\"
}
GetModifiedFileDateSSE () {
#$1 = the input file path
#$2 = returns input file modified date - Seconds Since Epoch
eval input_file=\"\$$1\"
[ -z "$OS_TYPE" ] && GetOSType OS_TYPE
{
if [ "$OS_TYPE" = "Linux" ] || [ "$OS_TYPE" = "Other" ]; then
current_modified_date_SSE="$(stat -c "%Y" "$input_file")" || { current_modified_date_SSE="-1"; }
elif [ "$OS_TYPE" = "BSD-based" ]; then
current_modified_date_SSE="$(stat -f "%m" "$input_file")" || { current_modified_date_SSE="-1"; }
fi
}||{
current_modified_date_SSE="-1"
}
eval $2=\"\$current_modified_date_SSE\"
}
GenerateMatchedFilesArrays () {
IFS='
'
i=0
cd "$initial_dir"
for current_search_path in $(eval find $search_path -prune -exec printf "%s\\\\n" {} + ); do
if [ ! -d "$current_search_path" ]; then
ExtractFirstAndLastPathComponent current_search_path fpc_current_search_path lpc_current_search_path
cd "$initial_dir"; cd "$fpc_current_search_path"; current_search_path="$PWD/$lpc_current_search_path"
find_zip_command="find \$current_search_path -type f -name \"*.zip*\""
elif [ -d "$current_search_path" ]; then
cd "$initial_dir"; cd "$current_search_path"; current_search_path="$PWD"
find_zip_command="find \$current_search_path/. -type f -name \"*.zip*\""
fi
for file1 in $(\
{ \
j=0;\
PrintJustInTitle "Step 1: Finding archive files..."
for file2 in $(\
eval "$find_zip_command";\
); do \
j=$(($j + 1)); \
PrintJustInTitle "Step 1: Processing file $j..."; \
GetFileSizeInBytes file2 file2_size_in_bytes; \
if [ "$file2_size_in_bytes" -le "$max_arhive_size_in_bytes" ]; then \
not_match="false"; \
for k in $(seq 1 $search_strings_array_0); do \
eval current_search_string=\"\$search_strings_array_$k\";\
eval unzip -q -c \"\$file2\" "$unzip_total_inside_archive_file_path_filter" 2>/dev/null|grep -l -i "$current_search_string">/dev/null||{ not_match="true"; break; }; \
done; \
if [ "$not_match" = "false" ]; then printf '%s\n' "$file2"; fi; \
fi; \
done|sort --numeric-sort|uniq -d;\
j=0;\
PrintJustInTitle "Step 2: Finding archive files..."
for file2 in $(\
eval "$find_zip_command";\
); do \
j=$(($j + 1)); \
PrintJustInTitle "Step 2: Processing file $j..." ; \
GetFileSizeInBytes file2 file2_size_in_bytes; \
if [ "$file2_size_in_bytes" -le "$max_arhive_size_in_bytes" ]; then \
not_match="false"; \
for k in $(seq 1 $search_strings_array_0); do \
eval current_search_string=\"\$search_strings_array_$k\";\
eval unzip -q -c \"\$file2\" "$unzip_total_inside_archive_file_path_filter" 2>/dev/null|grep -l -i "$current_search_string">/dev/null||{ not_match="true"; break; }; \
done; \
if [ "$not_match" = "false" ]; then printf '%s\n' "$file2"; fi; \
fi; \
done|sort --numeric-sort|uniq -u;\
}|sort --numeric-sort;\
PrintJustInTitle "Preparing to store necessary file info..."
); do
found="false"
previous_file_path="$current_file_path"
current_file_path="$file1"
if [ -z "$previous_file_path" ]; then
previous_file_path="$current_file_path"
found="true"
else
if [ ! "$current_file_path" = "$previous_file_path" ]; then
found="true"
fi
fi
if [ "$found" = "true" ]; then
i=$(($i + 1))
PrintJustInTitle "Storing necessary file info: file $i..."
eval current_file_path=\"\$file1\"
eval file_paths_$i=\"\$current_file_path\"
GetModifiedFileDateSSE current_file_path current_file_modified_date_SSE
eval file_modified_dates_SSE_$i=\"\$current_file_modified_date_SSE\"
GetModifiedFileDateFull current_file_path current_file_modified_date_full
if [ ! "${current_file_modified_date_full%"."*" "*}" = "$current_file_modified_date_full" ]; then
current_file_modified_date_full_part1="${current_file_modified_date_full%"."*" "*}"
current_file_modified_date_full_part2="${current_file_modified_date_full#$current_file_modified_date_full_part1"."*" "}"
current_file_modified_date_full="$current_file_modified_date_full_part1$current_file_modified_date_full_part2"
fi
eval file_modified_dates_full_$i=\"\$current_file_modified_date_full\"
GetFileSizeInBytes current_file_path current_file_path_size_in_bytes
eval file_size_$i=\"\$current_file_path_size_in_bytes\"
fi
done;
done
eval file_paths_0=$i
cd "$initial_dir"
PrintJustInTitle ""
}
PrintMatchedFilesInfo () {
PrintJustInTitle "Loading files data..."
for i in $(seq 1 $file_paths_0); do
PrintJustInTitle "Loading files data: file $i..."
eval current_file_path=\"\$file_paths_$i\"
eval current_file_modified_date_SSE=\"\$file_modified_dates_SSE_$i\"
eval current_file_modified_date_full=\"\$file_modified_dates_full_$i\"
eval current_file_size=\"\$file_size_$i\"
printf "%s \n" "$i"
printf "%s \n" "$(printf '%05d' "$i")"
printf "%s \n" "$current_file_path"
printf "%s \n" "$current_file_modified_date_SSE"
printf "%s \n" "$current_file_modified_date_full"
printf "%s \n" "$(printf '%015d%s' "$current_file_size" "B")"
done
}
CheckUtilities () {
#Check if any of the necessary utilities is missing:
error="false"
for utility; do
man -f $utility >/dev/null 2>/dev/null || { ErrorMessage "ERROR: the '$utility' utility is not installed!"; error="true"; }
done>&2
}
ErrorMessage () {
printf '\n%s\n' "$1">&2
}
PrintInTitle () {
printf "\033]0;%s\007" "$1"
}
PrintJustInTitle () {
PrintInTitle "$1">"$print_to_screen"
}
#Enable globbing (POSIX compliant):
set +f
#Enable globbing (zsh):
setopt no_nomatch 2>/dev/null
print_to_screen='/dev/tty' #print to screen only
max_arhive_size_in_bytes=100000000 #approx. 100 MB
Q="'"
NL2=$(printf '%s' "\n\n") #Store New Line for use with sed
GetOSType OS_TYPE
if [ "$OS_TYPE" = "Linux" ]; then
TEMPORARY_EXTRACT_PATH='/dev/shm' #RAM MEMORY
TEMP_EXTRACT_FOLDER='TEMP_EXTRACT_FOLDER'
man -f zenity>/dev/null 2>/dev/null||{ ErrorMessage "ERROR: The \"zenity\" utility is not installed!"; error="true"; }
elif [ "$OS_TYPE" = "BSD-based" ] || [ "$OS_TYPE" = "Other" ]; then
TEMPORARY_EXTRACT_PATH="$HOME" #$HOME folder
TEMP_EXTRACT_FOLDER='TEMP_EXTRACT_FOLDER'
man -f zenity>/dev/null 2>/dev/null||{ ErrorMessage "ERROR: The \"zenity\" utility is not installed - it can be installed with: \"brew install zenity\"!"; error="true"; }
fi
CheckUtilities stat mkdir rmdir unzip cat grep seq find sed file rm uniq sort
if [ "$OS_TYPE" = "Linux" ] || [ "$OS_TYPE" = "Other" ]; then
man -f gedit >/dev/null 2>/dev/null && {
editor_command1="gedit -w"
editor_command2="gedit --new-window -w"
} || {
man -f kate >/dev/null 2>/dev/null && {
editor_command1="kate"
editor_command2="kate --new-window"
} || {
ErrorMessage "ERROR: the 'gedit' or 'kate' utility is not installed!"
error="true"
}
}
elif [ "$OS_TYPE" = "BSD-based" ]; then
editor_command1="edit -w"
editor_command2="edit --new-window -w"
man -f edit >/dev/null 2>/dev/null || {
ErrorMessage "ERROR: the 'edit' utility is not installed (TextWrangler/BBEdit command-line tools)!"
error="true"
}
fi
if [ "$error" = "true" ]; then
printf "\n">&2
CleanUp; exit 1
fi
eval find /dev/null $find_search_archive_total_path_filter>/dev/null || {
printf "%s\n\n" "ERROR: Invalid find parameters provided!">&2
CleanUp; exit 1
}
###
initial_dir="$PWD"
output_dir=""
error="false"
{
cd "$TEMPORARY_EXTRACT_PATH" && {
if [ ! -e "$TEMP_EXTRACT_FOLDER" ]; then
printf '%s\n' "The specified temporary directory: \"$TEMP_EXTRACT_FOLDER\" - does not exist in the specified location: \"$TEMPORARY_EXTRACT_PATH\" - 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 "$TEMP_EXTRACT_FOLDER" || error="true"
fi
fi
cd "$TEMP_EXTRACT_FOLDER" && output_dir="$PWD" || {
error="true"
}
} || error="true"
} 2>/dev/null
if [ "$error" = "true" ]; then
printf '%s\n' "Error: Could not access temporary folder \"$TEMP_EXTRACT_FOLDER\" in the extract location: \"$TEMPORARY_EXTRACT_PATH\"!">&2
read temp
exit 1
fi
#Trap "INTERRUPT" (CTRL-C) and "TERMINAL STOP" (CTRL-Z) signals:
trap 'trap1' INT
trap 'trap1' TSTP
printf '\n%s\n' "For the next provided parameters:"
printf '\n%s\n' " - please quote:"
printf '%s\n' " - groups of single quotes (') within \"...\""
printf '%s\n' " - groups of double quotes (\") or groups of other characters within '...'"
printf '\n%s\n' " - please escape:"
printf '%s\n' " - literal '\' with '\' ('\\\\')"
printf '%s\n' " - if within double quotes (\"...\"): special characters have to be escaped with '\'"
printf '%s\n' " - if within single quotes ('...'): special characters (other than '\') don't have to be escaped"
printf "\n"
printf '\n%s\n' "Current_path = \"$initial_dir\"";
printf '\n%s\n' "Where to search path(s) (separated by space): "
printf '%s' ">> where to search path(s): >> "
read search_path;
if [ -z "$search_path" ]; then
printf '\n%s\n\n' "ERROR: Search path cannot be empty!"
exit 1
fi
printf '\n%s\n' "Inside archive file path filter: (what file path to lookup inside the archive) (default=Enter='*'):">"$print_to_screen"
current_inside_archive_file_path_filter="not_defined"
find_total_inside_archive_file_path_filter=""
unzip_total_inside_archive_file_path_filter=""
i=0;
while [ -n "$current_inside_archive_file_path_filter" ]; do
printf '%s' ">> add inside archive path filter (concatenated with logical OR): >> "
IFS= read -r current_inside_archive_file_path_filter
unset IFS #Reset IFS
if [ -n "$current_inside_archive_file_path_filter" ]; then
if [ -z "$find_total_inside_archive_file_path_filter" ]; then
find_total_inside_archive_file_path_filter="-path ""$current_inside_archive_file_path_filter"
else
find_total_inside_archive_file_path_filter="$find_total_inside_archive_file_path_filter -o -path ""$current_inside_archive_file_path_filter"
fi
unzip_total_inside_archive_file_path_filter="$unzip_total_inside_archive_file_path_filter"" ""$current_inside_archive_file_path_filter"
fi
done
if [ "$current_inside_archive_file_path_filter" = "not_defined" ]; then
find_total_inside_archive_file_path_filter='-path '"'"'*'"'"
unzip_total_inside_archive_file_path_filter="'"'*'"'"
fi
printf '\n%s\n' "Search string:">"$print_to_screen";
current_search_string="not_defined"
search_strings_array_0=0
i=0
while [ -n "$current_search_string" ]; do
printf '%s' ">> add search string (concatenated with logical AND): >> "
IFS= read -r current_search_string
unset IFS #Reset IFS
if [ -n "$current_search_string" ]; then
i=$(($i + 1))
eval search_strings_array_$i=\"\$current_search_string\"
fi
done
if [ ! "$i" = "0" ]; then
eval search_strings_array_0=$i
else
search_strings_array_1=""
search_strings_array_0=1
fi
printf '\n%s' "Also open files that match the file path filters but don't match the search string(s) (open them as a secondary group of files (in the same editor window))? [ Yes / No ] (default=Enter=No): "
read answer
if [ "$answer" = "Yes" ] || [ "$answer" = "yes" ] || [ "$answer" = "Y" ] || [ "$answer" = "y" ]; then
open_non_match_string_files="true"
else
open_non_match_string_files="false"
fi
IFS='
'
cd "$TEMPORARY_EXTRACT_PATH" && {
rmdir "$TEMP_EXTRACT_FOLDER" || {
printf '%s\n' "Error: Could not remove \"$TEMP_EXTRACT_FOLDER\" directory in: \"$TEMPORARY_EXTRACT_PATH\" - directory not empty (for security reasons - it has to be removed manualy)!">&2
exit 1
} && {
mkdir "$TEMP_EXTRACT_FOLDER"
}
} || {
printf '%s\n' "Error: Could not remove \"$TEMP_EXTRACT_FOLDER\" directory in: "$TEMPORARY_EXTRACT_PATH" - \"$TEMPORARY_EXTRACT_PATH\" is not accessible !">&2
exit 1
}
unset IFS
IFS='
'
cd "$initial_dir"
printf "\n">"$print_to_screen"
GenerateMatchedFilesArrays
pmfi_result="defined"
count=0
while [ -n "$pmfi_result" ]; do
PrintJustInTitle "Loading files data..."
count=$(($count + 1))
if [ ! "$count" = "1" ]; then
printf '%s\n\n' ">>>">"$print_to_screen"
fi
pmfi_result=$(zenity --list --separator='|' --multiple --width "1900" --height "900" --hide-column='1' --print-column='1' --column "Hidden column" --column "File Path number" --column "File Path" --column "Modified Date number" --column "Modified Date" --column "File Size" $(PrintMatchedFilesInfo; PrintJustInTitle "Building zenity list dialog..."))
sequence=""
pmfi_result_temp="$pmfi_result"
while [ -n "$pmfi_result_temp" ]; do
number="${pmfi_result_temp%%"|"*}"
if [ -z "$sequence" ]; then
sequence="$number"
else
sequence="$sequence"" ""$number"
fi
pmfi_result_temp="${pmfi_result_temp#"$number"}"
pmfi_result_temp="${pmfi_result_temp#"|"}"
done
sequence="${sequence%" "}"
j=0
unset IFS
for i in $(printf "$sequence"); do
padded_number="$(printf '%05d' "$i")"
eval current_file_path=\"\$file_paths_$i\"
ExtractFirstAndLastPathComponent current_file_path fpc_current_file_path lpc_current_file_path
cd "$fpc_current_file_path"
fpc_current_file_path="$PWD"
ExtractFirstAndLastPathComponent fpc_current_file_path fpc_fpc_current_file_path lpc_fpc_current_file_path
archive_name="${lpc_current_file_path%".zip"*}"
if [ ! -e "$output_dir/$padded_number/$lpc_fpc_current_file_path/$archive_name" ]; then
cd "$output_dir"
mkdir "$padded_number"
cd "$padded_number"
mkdir "$lpc_fpc_current_file_path"
cd "$lpc_fpc_current_file_path"
mkdir "$archive_name"
cd "$archive_name"
unzip -q "$current_file_path" -d "$output_dir/$padded_number/$lpc_fpc_current_file_path/$archive_name" 2>/dev/null
else
cd "$output_dir/$padded_number/$lpc_fpc_current_file_path/$archive_name"
fi
IFS='
'
new_group=""
for file3 in $(eval find . -type f "$find_total_inside_archive_file_path_filter"); do
GetFileEncoding file3 file3_encoding
if [ "$file3_encoding" = "text" ]; then
path4="$(printf '%s\n' "$output_dir/$padded_number/$lpc_fpc_current_file_path/$archive_name/$file3"|sed "s/'/$Q\"\$Q\"$Q/g")"
not_match="false"
for k in $(seq 1 $search_strings_array_0); do
eval current_search_string=\"\$search_strings_array_$k\"
cat "$output_dir/$padded_number/$lpc_fpc_current_file_path/$archive_name/$file3"|grep -l -i "$current_search_string">/dev/null||{ not_match="true"; break; }
done
if [ "$not_match" = "false" ]; then
new_group="$new_group"" ""'$path4'";
fi
fi
done
if [ "$open_non_match_string_files" = "true" ]; then
for file3 in $(eval find . -type f "$find_total_inside_archive_file_path_filter"); do
GetFileEncoding file3 file3_encoding
if [ "$file3_encoding" = "text" ]; then
path4="$(printf '%s\n' "$output_dir/$padded_number/$lpc_fpc_current_file_path/$archive_name/$file3"|sed "s/'/$Q\"\$Q\"$Q/g")"
not_match="false"
for k in $(seq 1 $search_strings_array_0); do
eval current_search_string=\"\$search_strings_array_$k\"
cat "$output_dir/$padded_number/$lpc_fpc_current_file_path/$archive_name/$file3"|grep -l -i "$current_search_string">/dev/null||{ not_match="true"; break; }
done
if [ "$not_match" = "true" ]; then
new_group="$new_group"" ""'$path4'";
fi
fi
done
fi
if [ -n "$new_group" ]; then
j=$(($j + 1))
eval groups_$j=\"\$new_group\"
fi
done
groups_0=$j
if [ ! "$groups_0" = "0" ]; then
eval $editor_command2 &
sleep 0.5
for i in $(seq 1 $groups_0); do
eval current_group="\"\$groups_$i\""
if [ "$i" = "1" ]; then
eval $editor_command1 "$current_group" &
sleep 0.5
else
eval $editor_command2 "$current_group" &
sleep 0.5
fi
done
fi
IFS='
'
done
unset IFS
sleep 1; CleanUp
cd "$initial_dir"
Or, as a 100% command line utility, after saving the next script - call it with the --help flag to find out how to use it:
#!/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
}
DisplayHelp () {
printf '\n%s\n' "Parameters Syntax:"
printf '\n%s\n\n' " [ flags ] <search_string> <inside_archive_path_filter> <search_path(s)>"
printf '%s\n' "For <search_string>, <inside_archive_path_filter> and <search_path(s)>:"
printf '%s\n' " Please quote groups of single quotes (') within \"...\" and groups of double quotes (\") or groups of other characters within '...'"
printf '%s\n' " If within double quotes (\"...\"): special characters have to be escaped with backslash (\) / if within single quotes ('...') special characters don't have to be escaped"
printf '%s\n' "Also, for <search_string>:"
printf '%s\n' " Literal '\' have to be escaped with '\' ('\\\\')"
printf '\n%s\n' "Flags:"
printf '%s\n' " -q / --quick (this is the default flag)"
printf '%s\n' " - prints only the archive paths (quicker than the rest of the flag options)"
printf '%s\n' " - <inside_archive_path_filter> is not required (it is considered '*')"
printf '%s\n' " -s / --short"
printf '%s\n' " - prints the archive paths and the inner file paths, without printing the matched file content"
printf '%s\n' " -d / --detailed"
printf '%s\n' " - prints the archive paths and the inner file paths, and also prints the matched file content"
printf '%s\n' " -h / --help"
printf '%s\n\n' " - displays this help information"
}
#Enable globbing (POSIX compliant):
set +f
#Enable globbing (zsh):
setopt no_nomatch 2>/dev/null
IFS='
'
print_to_screen='/dev/tty'
initial_dir="$PWD"
case "$(uname -s)" in
*"Linux"* )
#TEMPORARY_EXTRACT_PATH
TEP='/dev/shm' #RAM MEMORY
;;
*"Darwin"* | *"BSD"* | * )
#TEMPORARY_EXTRACT_PATH
TEP="$HOME" #$HOME folder
;;
esac
#TEMP_EXTRACT_FOLDER
TEF='TEMP_EXTRACT_FOLDER'
trap 'CleanUp' INT
trap 'CleanUp' TSTP
quick_flag="true" #default flag
short_flag="false"
detailed_flag="false"
help_flag="false"
search_string=""
inside_archive_path_filter=""
params_count=0
j=0
for param; do
case "$param" in
"-q" | "quick_flag=" )
quick_flag="true"
;;
"-s"|"--short" )
short_flag="true"
quick_flag="false"
;;
"-d"|"--detailed" )
detailed_flag="true"
quick_flag="false"
;;
"-h"|"--help" )
help_flag="true"
;;
* )
params_count=$(($params_count + 1))
if [ "$params_count" = "1" ]; then
search_string="$param"
elif [ "$params_count" = "2" ]; then
if [ ! "$quick_flag" = "true" ]; then
inside_archive_path_filter="'""$param""'"
else
printf '\n%s\n\n' "Warning: For the -q flag: Parameter 2: \"$param\" is treated as a <search_path> parameter (not as <inside_archive_path_filter> (which is skipped))!">"$print_to_screen"
j=$(($j + 1))
eval search_paths_$j=\"\$param\"
fi
else
j=$(($j + 1))
eval search_paths_$j=\"\$param\"
fi
;;
esac
done
search_paths_0=$j
if [ "$help_flag" = "true" ] || [ "$params_count" = "0" ]; then
DisplayHelp
exit 0
fi
printf '\n%s\n\n' "Current_path = \"$PWD\"";
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
cd "$initial_dir"
IFS='
'
if [ "$inside_archive_path_filter" = "''" ] || [ "$inside_archive_path_filter" = "\"\"" ]; then inside_archive_path_filter="'"'*'"'"; fi
i=0
PrintJustInTitle "Loading list of files to analyze..."
found_zip_file_match="false"
for k in $(seq 1 $search_paths_0); do
#current_search_path
eval CSP="\"\$search_paths_$k\""
cd "$initial_dir"
if [ ! -d "$CSP" ]; then
CSP2="$CSP"
CSP=""
find_zip_command="find \$CSP2 -type f -path \"*.zip*\" -exec printf '%s\\n' {} + "
else
cd "$CSP" && {
CSP="$PWD/"
find_zip_command="find . -type f -path \"*.zip*\" -exec printf '%s\n' {} + "
} || {
CleanUp 1
}
fi
eval "$find_zip_command" 2>/dev/null|sort --numeric-sort|{ while read -r zip_file
do
i=$(($i + 1))
PrintJustInTitle "Analyzing file $i..."
if [ "$quick_flag" = "true" ]; then #default flag
unzip -q -c "$zip_file" 2>/dev/null|grep -i -F "$search_string">/dev/null && {
printf '%s\n' "$CSP$zip_file"|grep --color -F "$CSP$zip_file"
found_zip_file_match="true"
}
elif [ "$short_flag" = "true" ]; then
unzip -q -c "$CSP$zip_file" 2>/dev/null|grep -i -F "$search_string">/dev/null && {
cd "$TEP" && {
unzip "$CSP$zip_file" -d "$TEF">/dev/null 2>/dev/null
cd "$output_dir"
j=0
for inside_zip_file in $(eval find . -type f -path "$inside_archive_path_filter"); do
j=$(($j + 1))
if [ "$j" = "1" ]; then
printf "\n"
printf '%s\n' "$CSP$zip_file:"
printf "\n"
else
cat "$inside_zip_file"|grep -i -F "$search_string">/dev/null 2>/dev/null && {
printf '%s\n' "$inside_zip_file"|grep --color -F "$inside_zip_file"
found_zip_file_match="true"
}
fi
done
if [ ! "$j" = "0" ]; then
printf "\n"
fi
if [ -n "$TEP" ] && [ -n "$TEF" ]; then
rm -R -f "$output_dir/"*
fi
cd "$CSP"
}
}
elif [ "$detailed_flag" = "true" ]; then
cd "$TEP" && {
unzip "$CSP$zip_file" -d "$TEF">/dev/null 2>/dev/null
cd "$output_dir"
for inside_zip_file in $(eval find . -type f -path "$inside_archive_path_filter"); do
cat "$inside_zip_file"|grep -i -F "$search_string">/dev/null 2>/dev/null && {
printf "\n"
printf '%s\n' "$CSP$zip_file/$inside_zip_file"|grep --color -F "$CSP$zip_file/$inside_zip_file"
printf "\n"
cat "$inside_zip_file"|grep -i -F "$search_string"
found_zip_file_match="true"
}
done
if [ -n "$TEP" ] && [ -n "$TEF" ]; then
rm -R -f "$output_dir/"*
fi
cd "$CSP"
}
fi
done;
if [ "$k" = "$search_paths_0" ] && [ "$found_zip_file_match" = "true" ]; then printf "\n"; else printf '%s\n\n' "No results found."; fi
}
done
PrintJustInTitle ""
CleanUp