30

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?

4 Answers4

18

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".

14

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
Anwar
  • 77,855
7

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
nelaaro
  • 10,338
2

Here's a dash script for searching inside archive files (should also work with: bash, zsh, ksh shells):

Simply call the script with no parameters and the script will prompt for the necessary input:

#!/bin/dash
## Supported shells: dash, bash, zsh, ksh

GetOSType () { #$1 = returns the type of the current operating system:

case "$(uname -s)" in
*"Linux"* )
    eval $1="Linux"
    ;;
*"Darwin"* | *"BSD"* )
    eval $1="BSD-based"
    ;;
* )
    eval $1="Other"
    ;;
esac

}

TestIfFileIsText () { #$1 = input file path #$2 = returns "true" if the input file is text, "false" otherwise

result="false"
eval current_file=\"\$$1\"
current_file_mime_type="$(file -bL --mime-encoding "$current_file" 2>/dev/null)"
case "$current_file_mime_type" in
    *"ascii"* | *"utf"* )
        result="true"
    ;;
esac
eval $2=\"\$result\"

}

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 '/' characters:
    while [ ! "${current_path%"/"}" = "$current_path" ]; do
        current_path="${current_path%"/"}"
    done

    if [ -z "$current_path" ]; then
        eval current_path=\"\$$1\"
    fi

    last_path_component="${current_path##*"/"}"
    first_path_component="${current_path%"$last_path_component"}"
fi

eval $2="\"\$first_path_component\""
eval $3="\"\$last_path_component\""

}

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"

}

PrintErrorMessage () { #Prints the total string parameters received by this function as a single error message:

printf '\n%s\n' "${@}">&2

}

PrintErrorMessageAndSetError () { #Prints the total string the parameters received by this function as a single error message and sets the <error> variable to "true":

printf '\n%s\n' &quot;${@}&quot;&gt;&amp;2
error=&quot;true&quot;

}

trap1 () { #Calls the 'CleanUp' function after pressing "CTRL + C / CTRL + Z" and ends all the processes started by this script:

printf &quot;\n&quot;&quot;Aborted.\n&quot;&gt;&gt;&quot;$print_to_screen&quot;

CleanUp

#kill all children processes, suppressing &quot;Terminated&quot; message:
kill -s PIPE -- -$$ 2&gt;/dev/null

exit

}

CleanUp () { #Removes temporary generated files and restores CTRL + C / CTRL + Z and other settings to their original role (i.e. as before running this script):

if [ -n &quot;$TEMPORARY_EXTRACT_PATH&quot; ] &amp;&amp; [ -n &quot;$output_dir&quot; ]; then
    rm -R -f &quot;$output_dir&quot;'/''TEMP_EXTR_FOLDER''/'* #WARNING: EDIT WITH CAUTION!!!
fi

#Restore &quot;INTERRUPT&quot; (CTRL + C) and &quot;TERMINAL STOP&quot; (CTRL + Z) signals:
trap - INT
trap - TSTP

#Clear the title:
printf &quot;\033]0;%s\007&quot; &quot;&quot;&gt;&gt;&quot;$print_to_screen&quot;

RestoreIFS initial_IFS

}

StoreIFS () { #Stores the IFS's variable value to the specified $1 variable:

eval $1=&quot;\&quot;\$IFS\&quot;&quot;

}

RestoreIFS () { #Restore the IFS variable to the specified $1 variable value:

eval IFS=&quot;\&quot;\$$1\&quot;&quot;

}

GetModifiedFileDateFull () { #$1 = the input file path #$2 = returns input file modified date

eval input_file=\&quot;\$$1\&quot;
[ -z &quot;$OS_TYPE&quot; ] &amp;&amp; GetOSType OS_TYPE
{
    if [ &quot;$OS_TYPE&quot; = &quot;Linux&quot; ] || [ &quot;$OS_TYPE&quot; = &quot;Other&quot; ]; then
        current_modified_date_full=&quot;$(stat -c &quot;%y&quot; &quot;$input_file&quot;)&quot; || { current_modified_date_full=&quot;-1&quot;; }
    elif [ &quot;$OS_TYPE&quot; = &quot;BSD-based&quot; ]; then
        current_modified_date_full=&quot;$(stat -f &quot;%Sm&quot; &quot;$input_file&quot;)&quot; || { current_modified_date_full=&quot;-1&quot;; }
    fi
}||{
    current_modified_date_full=&quot;-1&quot;
}
eval $2=\&quot;\$current_modified_date_full\&quot;

}

GetModifiedFileDateSSE () { #$1 = the input file path #$2 = returns input file modified date - Seconds Since Epoch

eval input_file=\&quot;\$$1\&quot;
[ -z &quot;$OS_TYPE&quot; ] &amp;&amp; GetOSType OS_TYPE
{
    if [ &quot;$OS_TYPE&quot; = &quot;Linux&quot; ] || [ &quot;$OS_TYPE&quot; = &quot;Other&quot; ]; then
        current_modified_date_SSE=&quot;$(stat -c &quot;%Y&quot; &quot;$input_file&quot;)&quot; || { current_modified_date_SSE=&quot;-1&quot;; }
    elif [ &quot;$OS_TYPE&quot; = &quot;BSD-based&quot; ]; then
        current_modified_date_SSE=&quot;$(stat -f &quot;%m&quot; &quot;$input_file&quot;)&quot; || { current_modified_date_SSE=&quot;-1&quot;; }
    fi
}||{
    current_modified_date_SSE=&quot;-1&quot;
}
eval $2=\&quot;\$current_modified_date_SSE\&quot;

}

GenerateMatchedFilesArrays () { #Generates matched <ARCHIVE PATHS> array and for each path: <MODIFIED DATE SECONDS SINCE EPOCH>, <MODIFIED DATE (LOCAL TIME)>, <SIZE IN BYTES> - arrays:

IFS='

' i=0 cd "$initial_dir"

archive_type_1='.zip'
archive_type_2='.tar.bz2'
archive_type_3='.tar.xz'
archive_type_4='.tar.gz'
archive_type_5='.7z'
archive_type_6='.rar'
archive_type_7='.bz2'
archive_type_8='.xz'
archive_type_9='.gz'
archive_type_10='.tgz'
archive_type_11='.tar'
archive_type_0=&quot;11&quot;

find_commands_0=&quot;$archive_type_0&quot;
extract_to_screen_commands_1=&quot;unzip -q -c \&quot;\$file2\&quot; $total_in_archive_file_path_filters&quot;
extract_to_screen_commands_2=&quot;tar -xOjf \&quot;\$file2\&quot; --wildcards $total_in_archive_file_path_filters&quot;
extract_to_screen_commands_3=&quot;tar -xOJf \&quot;\$file2\&quot; --wildcards $total_in_archive_file_path_filters&quot;\
extract_to_screen_commands_4=&quot;tar -xOzf \&quot;\$file2\&quot; --wildcards $total_in_archive_file_path_filters&quot;
extract_to_screen_commands_5=&quot;7z e \&quot;\$file2\&quot;&quot;
extract_to_screen_commands_6=&quot;unrar p \&quot;\$file2\&quot;&quot;
extract_to_screen_commands_7=&quot;bzip2 -dc \&quot;\$file2\&quot;&quot;
extract_to_screen_commands_8=&quot;xz -dc \&quot;\$file2\&quot;&quot;
extract_to_screen_commands_9=&quot;gzip -dc \&quot;\$file2\&quot;&quot;
extract_to_screen_commands_10=&quot;tar -xOzf \&quot;\$file2\&quot;&quot; ## ERROR: NO OUTPUT GENERATED (LINUX)
extract_to_screen_commands_11=&quot;tar -xOf \&quot;\$file2\&quot;&quot; ## ERROR: NO OUTPUT GENERATED (LINUX)
extract_to_screen_commands_0=&quot;11&quot;

for current_search_path in $(eval find \&quot;\$search_path\&quot; -prune -exec printf &quot;%s\\\\n&quot; {} + ); do

    if [ ! -d &quot;$current_search_path&quot; ]; then
        ExtractFirstAndLastPathComponent current_search_path fpc_current_search_path lpc_current_search_path
        cd &quot;$initial_dir&quot;; cd &quot;$fpc_current_search_path&quot;; current_search_path=&quot;$PWD/$lpc_current_search_path&quot;
        for j in $(GenerateSequence 1 $archive_type_0); do
            eval current_archive_type=&quot;\&quot;\$archive_type_$j\&quot;&quot;
            eval find_commands_$j=&quot;\&quot;find \\\&quot;\\\$current_search_path\\\&quot; -type f -name \\\&quot;*$current_archive_type\\\&quot;\&quot;&quot;
        done
    elif [ -d &quot;$current_search_path&quot; ]; then
        cd &quot;$initial_dir&quot;; cd &quot;$current_search_path&quot;; current_search_path=&quot;$PWD&quot;
        for j in $(GenerateSequence 1 $archive_type_0); do
            eval current_archive_type=&quot;\&quot;\$archive_type_$j\&quot;&quot;
            eval find_commands_$j=&quot;\&quot;find \\\&quot;\\\$current_search_path/.\\\&quot; -type f -name \\\&quot;*$current_archive_type\\\&quot;\&quot;&quot;
        done
    fi

    for file1 in $(\
        { \
        j=0;\
        for l in $(GenerateSequence 1 $find_commands_0); do \
            eval current_find_command=\&quot;\$find_commands_$l\&quot;; \
            eval current_extract_to_screen_command=\&quot;\$extract_to_screen_commands_$l\&quot;; \
            eval current_archive_type=\&quot;\$archive_type_$l\&quot;

            PrintJustInTitle &quot;Step 1: Finding $current_archive_type archive files...&quot;; \

            GenerateMatchedFilePaths 1|uniq -d;\
            j=0;\

            PrintJustInTitle &quot;Step 2: Finding $current_archive_type archive files...&quot;; \

            GenerateMatchedFilePaths 2|uniq -u;\
        done; \
        }|sort --numeric-sort;\
        PrintJustInTitle &quot;Preparing to store necessary file info...&quot;; \
    ); do
        found=&quot;false&quot;
        previous_file_path=&quot;$current_file_path&quot;
        current_file_path=&quot;$file1&quot;
        if [ -z &quot;$previous_file_path&quot; ]; then
            previous_file_path=&quot;$current_file_path&quot;
            found=&quot;true&quot;
        else
            if [ ! &quot;$current_file_path&quot; = &quot;$previous_file_path&quot; ]; then
                found=&quot;true&quot;
            fi
        fi

        if [ &quot;$found&quot; = &quot;true&quot; ]; then
            i=$(($i + 1))
            PrintJustInTitle &quot;Storing necessary file info: file $i...&quot;
            eval current_file_path=\&quot;\$file1\&quot;
            eval archive_paths_$i=\&quot;\$current_file_path\&quot;
            GetModifiedFileDateSSE current_file_path current_file_modified_date_SSE
            eval file_modified_dates_SSE_$i=\&quot;\$current_file_modified_date_SSE\&quot;
            GetModifiedFileDateFull current_file_path current_file_modified_date_full
            if [ ! &quot;${current_file_modified_date_full%&quot;.&quot;*&quot; &quot;*}&quot; = &quot;$current_file_modified_date_full&quot; ]; then
                current_file_modified_date_full_part1=&quot;${current_file_modified_date_full%&quot;.&quot;*&quot; &quot;*}&quot;
                current_file_modified_date_full_part2=&quot;${current_file_modified_date_full#$current_file_modified_date_full_part1&quot;.&quot;*&quot; &quot;}&quot;
                current_file_modified_date_full=&quot;$current_file_modified_date_full_part1$current_file_modified_date_full_part2&quot;
            fi
            eval file_modified_dates_full_$i=\&quot;\$current_file_modified_date_full\&quot;
            GetFileSizeInBytes current_file_path current_file_path_size_in_bytes
            eval file_size_$i=\&quot;\$current_file_path_size_in_bytes\&quot;
        fi
    done;
done
eval archive_paths_0=$i

cd &quot;$initial_dir&quot;
PrintJustInTitle &quot;&quot;

}

GenerateMatchedFilePaths () { #For the variable received as parameter (containing a <find command>) -> print all file paths that match the <search criterias> specified by the user:

for file2 in $(\
    eval &quot;$current_find_command&quot;;\
); do \
    j=$(($j + 1)); \
    PrintJustInTitle &quot;Step $1: Processing file $j...&quot;; \
    GetFileSizeInBytes file2 file2_size_in_bytes; \
    if [ &quot;$file2_size_in_bytes&quot; -le &quot;$max_archive_size_in_bytes&quot; ]; then \
        not_match=&quot;false&quot;; \
        for k in $(GenerateSequence 1 $search_strings_array_0); do \
            eval current_search_string=\&quot;\$search_strings_array_$k\&quot;;\
            eval $current_extract_to_screen_command 2&gt;/dev/null|grep -l -i &quot;$current_search_string&quot;&gt;/dev/null||{ not_match=&quot;true&quot;; break; }; \
        done; \
        if [ &quot;$not_match&quot; = &quot;false&quot; ]; then printf '%s\n' &quot;$file2&quot;; fi; \
    else \
        printf '%s\n' &quot;Skipping large archive (max_archive_size_in_bytes=$max_archive_size_in_bytes): $file2...&quot;&gt;&gt;&quot;$print_to_screen&quot;;\
    fi; \
done|sort --numeric-sort

}

PrintMatchedFilesInfo () { #For each file in the <ARCHIVE PATHS> array: print the file's: PATH, MODIFIED DATE SECONDS SINCE EPOCH, MODIFIED DATE (LOCAL TIME), SIZE IN BYTES -> for use with 'zenity':

printf '%s\n\n' &quot;&gt;&gt;&gt;&quot;&gt;&gt;&quot;$print_to_screen&quot;
sleep 1

for i in $(GenerateSequence 1 $archive_paths_0); do
    PrintJustInTitle &quot;Loading files data: file $i...&quot;
    eval current_file_path=\&quot;\$archive_paths_$i\&quot;
    eval current_file_modified_date_SSE=\&quot;\$file_modified_dates_SSE_$i\&quot;
    eval current_file_modified_date_full=\&quot;\$file_modified_dates_full_$i\&quot;
    eval current_file_size=\&quot;\$file_size_$i\&quot;
    printf &quot;%s \n&quot; &quot;$i&quot;
    printf &quot;%s \n&quot; &quot;$(printf '%05d' &quot;$i&quot;)&quot;
    printf &quot;%s \n&quot; &quot;$current_file_path&quot;
    printf &quot;%s \n&quot; &quot;$current_file_modified_date_SSE&quot;
    printf &quot;%s \n&quot; &quot;$current_file_modified_date_full&quot;
    printf &quot;%s \n&quot; &quot;$(printf '%015d%s' &quot;$current_file_size&quot; &quot;B&quot;)&quot;
done

}

CheckUtilities () { #Check if any of the necessary utilities (received as string parameters by this function) is missing:

error=&quot;false&quot;

for utility; do
    which $utility&gt;/dev/null 2&gt;/dev/null || PrintErrorMessageAndSetError &quot;ERROR: the '$utility' utility is not installed!&quot;
done

}

PrintInTitle () { #Changes the terminal emulator window title to: $1:

printf &quot;\033]0;%s\007&quot; &quot;$1&quot;

}

PrintJustInTitle () { #Changes the terminal emulator window title to: $1 (survives output redirection):

PrintInTitle &quot;$1&quot;&gt;&gt;&quot;$print_to_screen&quot;

}

PressEnterToExit () { #Waits for the user to press Enter in order to exit:

printf '%s\n' &quot;Press Enter to exit...&quot;
read temp

}

GenerateSequence () { #Prints the sequence of numbers $1 .. $2 <-> if $1 value < $2 value:

sequence_start=$(($1))
sequence_end=$(($2))
if [ &quot;$sequence_start&quot; -le &quot;$sequence_end&quot; ]; then
    seq $sequence_start $sequence_end
fi

}

print_to_screen='/dev/tty' #Print text to screen only

{

set +f #Enable globbing (POSIX compliant) setopt no_nomatch 2>/dev/null #Enable globbing (zsh)

Q="'" max_archive_size_in_bytes=100000000 #approx. 100 MB initial_dir="$PWD" StoreIFS initial_IFS

GetOSType OS_TYPE

CheckUtilities stat mkdir rmdir unzip cat grep seq find sed file rm uniq sort

#Trap "INTERRUPT" (CTRL + C) and "TERMINAL STOP" (CTRL + Z) signals: trap 'trap1' INT trap 'trap1' TSTP

{ [ "$OS_TYPE" = "Linux" ] || [ "$OS_TYPE" = "Other" ] && { which gedit 2>/dev/null && { editor_open_in_same_window_and_wait="gedit -w" editor_open_in_new_window_and_wait="gedit --new-window -w" editor_open_new_blank_window_and_wait="$editor_open_in_new_window_and_wait" } || { which kate 2>/dev/null && { editor_open_in_same_window_and_wait="kate -w" editor_open_in_new_window_and_wait="kate -n -w" editor_open_new_blank_window_and_wait="$editor_open_in_new_window_and_wait" } } 2>/dev/null || { PrintErrorMessageAndSetError "ERROR: Text editor not found (gedit / kate)!" PressEnterToExit }>&2 } 2>/dev/null || { [ "$OS_TYPE" = "BSD-based" ] && { #which bbedit && { # editor_open_in_same_window_and_wait="open -a bbedit -W" # editor_open_in_new_window_and_wait="open -a bbedit -n -W" # editor_open_new_blank_window_and_wait="$editor_open_in_new_window_and_wait" #} 2>/dev/null || { # which TextEdit && { editor_open_in_same_window_and_wait="open -a TextEdit -W" editor_open_in_new_window_and_wait="open -a TextEdit -n -W" editor_open_new_blank_window_and_wait="$editor_open_in_new_window_and_wait" # } 2>/dev/null || { # PrintErrorMessageAndSetError "ERROR: Text editor not found (bbedit / TextEdit)!" # PressEnterToExit # }>&2 #} } } || { PrintErrorMessageAndSetError "ERROR: Unsupported OS!" sleep 1 }>&2 }>/dev/null

if [ "$error" = "true" ]; then #printf "\n" CleanUp exit 1 fi

eval find /dev/null $find_search_archive_total_path_filter>/dev/null || { PrintErrorMessage "ERROR: Invalid find parameters provided!" CleanUp exit 1 }>&2

initial_dir="$PWD"

if [ "$OS_TYPE" = "Linux" ] || [ "$OS_TYPE" = "Other" ]; then if [ -e '/dev/shm' ]; then TEMPORARY_EXTRACT_PATH='/dev/shm' elif [ -e "$HOME" ]; then TEMPORARY_EXTRACT_PATH="$HOME" else PrintErrorMessage "Please provide TEMPORARY_EXTRACT_PATH: " read TEMPORARY_EXTRACT_PATH fi elif [ "$OS_TYPE" = "BSD-based" ] && [ -e "$HOME" ]; then TEMPORARY_EXTRACT_PATH="$HOME" else printf '%s\n' "Please provide TEMPORARY_EXTRACT_PATH: ">&2 read TEMPORARY_EXTRACT_PATH fi

TEMPORARY_EXTRACT_FOLDER='TEMP_EXTR_FOLDER' # HARDCODED STRING (SHOULD NOT BE CHANGED)

output_dir="" error="false" { cd "$TEMPORARY_EXTRACT_PATH" && { output_dir="$PWD" if [ ! -e "TEMP_EXTR_FOLDER" ]; then printf '%s\n' "The specified temporary directory: &quot;TEMP_EXTR_FOLDER&quot; - does not exist in the specified location: &quot;$TEMPORARY_EXTRACT_PATH&quot; - do you want to create it? [ Yes / No ] (default=Enter=No): " read answer if [ "$answer" = "Yes" ] || [ "$answer" = "yes" ] || [ "$answer" = "Y" ] || [ "$answer" = "y" ]; then mkdir "TEMP_EXTR_FOLDER" || error="true" fi fi cd "TEMP_EXTR_FOLDER" || { error="true" } } || error="true" } 2>/dev/null if [ "$error" = "true" ]; then PrintErrorMessage "Error: Could not access temporary folder &quot;TEMP_EXTR_FOLDER&quot; in the extract location: &quot;$TEMPORARY_EXTRACT_PATH&quot;!" PressEnterToExit exit 1 fi>&2

cd "$initial_dir" printf "\n" printf '%s\n' "Current_path = &quot;$initial_dir&quot;"; printf "\n" printf '%s\n' "Where to search path (unquoted (raw)) (default=Enter=.): " printf '%s' ">> where to search path: >> " read -r search_path; [ -z "$search_path" ] && search_path="." if [ ! -e "$search_path" ]; then PrintErrorMessage "ERROR: The provided search path: &quot;$search_path&quot; does not exist!" PressEnterToExit exit 1 fi>&2 if [ -d "$search_path" ]; then cd "$search_path" || { PrintErrorMessage "ERROR: Could not access search dir: &quot;$search_path&quot;!" PressEnterToExit exit 1 }>&2 cd "$initial_dir" fi

printf '\n%s\n' "In-archive file path filter(s): (what file path to lookup in the archive) (default=Enter=&quot;&quot;):">>"$print_to_screen" current_in_archive_file_path_filter="not_defined" i=0; while [ -n "$current_in_archive_file_path_filter" ]; do printf '%s' ">> add in-archive path filter (concatenated internally with logical OR): >> " IFS= read -r current_in_archive_file_path_filter RestoreIFS initial_IFS if [ -n "$current_in_archive_file_path_filter" ]; then i=$(($i + 1)) eval in_archive_file_path_filters_$i=&quot;$current_in_archive_file_path_filter&quot; total_in_archive_file_path_filters="$total_in_archive_file_path_filters $current_in_archive_file_path_filter" fi done if [ "$i" = "0" ]; then i=$(($i + 1)) in_archive_file_path_filters_1='""' fi in_archive_file_path_filters_0=$i

printf '\n%s\n' "Search string:"; current_search_string="not_defined" search_strings_array_0=0 i=0 while [ -n "$current_search_string" ]; do printf '%s' ">> add search string (RegEx) (concatenated internally with logical AND): >> " IFS= read -r current_search_string RestoreIFS initial_IFS if [ -n "$current_search_string" ]; then i=$(($i + 1)) eval search_strings_array_$i=&quot;$current_search_string&quot; 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 "$initial_dir"

printf "\n"

GenerateMatchedFilesArrays pmfi_result="defined" count=0 while [ -n "$pmfi_result" ]; do PrintJustInTitle "Loading files data..."

count=$(($count + 1))

pmfi_result=$(zenity --list --separator='|' --multiple --width &quot;1900&quot; --height &quot;900&quot; --hide-column='1' --print-column='1' --column &quot;Hidden column&quot; --column &quot;File Path number&quot; --column &quot;File Path&quot; --column &quot;Modified Date number&quot; --column &quot;Modified Date&quot; --column &quot;File Size&quot; $(PrintJustInTitle &quot;Loading files data...&quot;; PrintMatchedFilesInfo; PrintJustInTitle &quot;Please select archives to preview...&quot;))

sequence=&quot;$pmfi_result&quot;
t=0
temp=&quot;&quot;
while [ ! &quot;$temp&quot; = &quot;$sequence&quot; ]; do
    temp=&quot;$sequence&quot;
    current_number=&quot;${temp%%&quot;|&quot;*}&quot;
    t=$(($t + 1))
    eval numbers_$t=$(($current_number))
    sequence=&quot;${temp#*$number*&quot;|&quot;}&quot;
done
numbers_0=$t

RestoreIFS initial_IFS

j=0
for i in $(GenerateSequence 1 $numbers_0); do

    eval current_number=\&quot;\$numbers_$i\&quot;

    padded_number=&quot;$(printf '%05d' &quot;$current_number&quot;)&quot;
    eval current_archive_path=\&quot;\$archive_paths_$current_number\&quot;
    full_current_archive_path=&quot;$current_archive_path&quot;

    ExtractFirstAndLastPathComponent current_archive_path fpc_current_archive_path lpc_current_archive_path
    cd &quot;$fpc_current_archive_path&quot;
    fpc_current_archive_path=&quot;$PWD&quot;

    ExtractFirstAndLastPathComponent fpc_current_archive_path fpc_fpc_current_archive_path lpc_fpc_current_archive_path
    current_archive_name_ext=&quot;${lpc_current_archive_path}&quot;
    current_archive_name_ext_plus=&quot;${current_archive_name_ext}&quot;&quot;_extract&quot;
    full_current_archive_extract_to_path=&quot;$output_dir&quot;'/''TEMP_EXTR_FOLDER'&quot;/$padded_number/$lpc_fpc_current_archive_path/$current_archive_name_ext_plus&quot;

    if [ ! -e &quot;$full_current_archive_extract_to_path&quot; ]; then
        cd &quot;$output_dir&quot;'/''TEMP_EXTR_FOLDER'
        mkdir &quot;$padded_number&quot;
        cd &quot;$padded_number&quot;
        mkdir &quot;$lpc_fpc_current_archive_path&quot;
        cd &quot;$lpc_fpc_current_archive_path&quot;
        mkdir &quot;$current_archive_name_ext_plus&quot;
        cd &quot;$current_archive_name_ext_plus&quot;

        case &quot;$current_archive_path&quot; in
            *'.zip' )
                unzip &quot;$full_current_archive_path&quot; -d &quot;$full_current_archive_extract_to_path&quot;
            ;;
            *'.7z' )
                7z x &quot;$full_current_archive_path&quot; -o&quot;$full_current_archive_extract_to_path/&quot;
            ;;
            *'.rar' )
                unrar x &quot;$full_current_archive_path&quot; &quot;$full_current_archive_extract_to_path/&quot;
            ;;
            *'.tar.bz2' )
                tar -xvjf &quot;$full_current_archive_path&quot; -C &quot;$full_current_archive_extract_to_path&quot;
            ;;
            *'.tar.xz' )
                tar -xvJf &quot;$full_current_archive_path&quot; -C &quot;$full_current_archive_extract_to_path&quot;
            ;;
            *'.tar.gz' | *'.tgz' )
                tar -xvzf &quot;$full_current_archive_path&quot; -C &quot;$full_current_archive_extract_to_path&quot;
            ;;
            *'.tar' )
                tar -xvf &quot;$full_current_archive_path&quot; -C &quot;$full_current_archive_extract_to_path&quot;
            ;;
            *'.bz2' | *'.xz' | *'.gz' )
                cp &quot;$full_current_archive_path&quot; &quot;$full_current_archive_extract_to_path&quot;
                case &quot;$current_archive_path&quot; in
                    *'.bz2' ) bzip2 &quot;$full_current_archive_extract_to_path/&quot;&quot;$current_archive_name_ext&quot; -d &quot;$full_current_archive_extract_to_path&quot;; ;;
                    *'.xz' ) xz &quot;$full_current_archive_extract_to_path/&quot;&quot;$current_archive_name_ext&quot; -d &quot;$full_current_archive_extract_to_path&quot;; ;;
                    *'.gz' ) gzip -d &quot;$full_current_archive_extract_to_path/&quot;&quot;$current_archive_name_ext&quot;; ;;
                esac
                case &quot;${current_archive_name_ext%&quot;.&quot;*}&quot; in
                    *'.tar' )
                        tar -xvf &quot;$full_current_archive_extract_to_path/${current_archive_name_ext%&quot;.&quot;*}&quot; -C &quot;$full_current_archive_extract_to_path&quot;
                        #rm &quot;$full_current_archive_extract_to_path/${current_archive_name_ext%&quot;.&quot;*}&quot;
                        rm &quot;$output_dir&quot;'/''TEMP_EXTR_FOLDER'&quot;/$padded_number/$lpc_fpc_current_archive_path/$current_archive_name_ext_plus&quot;&quot;/&quot;&quot;${current_archive_name_ext%&quot;.&quot;*}&quot; #WARNING: EDIT WITH CAUTION!!!
                    ;;
                esac
            ;;
        esac &gt;/dev/null 2&gt;/dev/null
    else
        cd &quot;$full_current_archive_extract_to_path&quot;
    fi

    new_group=&quot;&quot;

    for m in $(GenerateSequence 1 $in_archive_file_path_filters_0); do
        eval current_in_archive_path_filter=\&quot;\$in_archive_file_path_filters_$m\&quot;
        IFS=' '
        for current_group_no in 1 2; do
            IFS='

' if [ "$current_group_no" = "2" ] && [ -z "$new_group" ]; then break fi for current_in_archive_file_path in $(eval find . -type f -path $current_in_archive_path_filter|sort --numeric-sort); do TestIfFileIsText current_in_archive_file_path in_archive_file_is_text if [ "$in_archive_file_is_text" = "true" ]; then matched_group="1" for k in $(GenerateSequence 1 $search_strings_array_0); do eval current_search_string=&quot;$search_strings_array_$k&quot; cat "$full_current_archive_extract_to_path/$current_in_archive_file_path"|grep -l -i "$current_search_string">/dev/null||{ matched_group="2"; break; } done

                    if [ &quot;$matched_group&quot; = &quot;$current_group_no&quot; ] &amp;&amp; ( ! ( [ &quot;$open_non_match_string_files&quot; = &quot;false&quot; ] &amp;&amp; [ &quot;$current_group_no&quot; = &quot;2&quot; ] ) ); then
                        esc_full_current_extr_file_path=&quot;$(printf '%s\n' &quot;$full_current_archive_extract_to_path/$current_in_archive_file_path&quot;|sed &quot;s/'/$Q\&quot;\$Q\&quot;$Q/g&quot;)&quot;; new_group=&quot;$new_group&quot;&quot; &quot;&quot;'$esc_full_current_extr_file_path'&quot;
                    fi
                fi
            done
            IFS=' '
        done
        RestoreIFS initial_IFS
    done

    if [ -n &quot;$new_group&quot; ]; then
        j=$(($j + 1))
        eval groups_$j=\&quot;\$new_group\&quot;
        eval matched_archive_paths_$j=\&quot;\$current_archive_path\&quot;
    fi
done

groups_0=$j
matched_archive_paths_0=$j

RestoreIFS initial_IFS
first_time=&quot;true&quot;
for i in $(GenerateSequence 1 $groups_0); do
    eval current_group=&quot;\&quot;\$groups_$i\&quot;&quot;
    if [ &quot;$first_time&quot; = &quot;true&quot; ]; then
        { eval $editor_open_new_blank_window_and_wait &amp; }
        sleep 0.5
        { eval $editor_open_in_same_window_and_wait &quot;$current_group&quot; &amp; }
        first_time=&quot;false&quot;
    else
        { eval $editor_open_in_new_window_and_wait &quot;$current_group&quot; &amp; }
    fi
    sleep 0.5
done

IFS='

' done RestoreIFS initial_IFS

PrintJustInTitle "Exiting..."; sleep 1; CleanUp cd "$initial_dir"

}>>"$print_to_screen"

Note: In order to be able to display a customized (personal) terminal emulator window title - some terminal emulators, such as konsole, require one initial additional step - for the konsole terminal emulator, this step is:

Konsole -> Settings -> Configure Konsole ... ->
-> Enable option "Show window title on the titlebar"
I. Marin
  • 31
  • 2