Search code examples
bashassociative-arrayunzip

Unzip list of files from bash associative array keys


My bash script create an associative array with files as keys.

declare -A fileInFolder
for f in "${zipFolder}/"*".zip"; do
    read -r fileInFolder[$f] _ < <(md5sum "$f")
done

... code for removing some entry in fileInFolder ...

unzip -qqc "${!fileInFolder[@]}"

And unzip prevent me caution: filename not matched: for everyone except first file.

The following command work without any problem:

unzip -qqc "${zipFolder}/"\*".zip"

I try using 7z but I did't find the way to give more than one zip file as input (using -ai option this need a list of file separated by new line if my understanding is correct...)


Solution

    • Ignoring the reason for the Associative array storing MD5 of zip files.
    • As @Enrico Maria De Angelis pointed-out, unzip only accepts one zip file argument per invocation. So you can not expand the associative array file names indexes into arguments for a single call to unzip.

    I propose this solution:

    #!/usr/bin/env bash
    
    # You don't want to unzip the pattern name if none match
    shopt -s nullglob
    
    declare -A fileInFolder
    for f in "${zipFolder}/"*".zip"; do
        # Store MD5 of zip file into assoc array fileInFolder
        # key: zip file name
        # value: md5sum of zip file
        read -r fileInFolder["$f"] < <(md5sum "$f")
        # Unzip file content to stdout
        unzip -qqc "$f"
    done | {
     # Stream the for loop's stdout to the awk script
     awk -f script.awk
    }
    

    Alternative implementation calling md5sum only once for all zip files

    shopt -s nullglob
    
    # Iterate the null delimited entries output from md5sum
    # Reading first IFS=' ' space delimited field as sum
    # and remaining of entry until null as zipname
    while IFS=' ' read -r -d '' sum zipname; do
      # In case md5sum file patterns has no match
      # It will return the md5sum of stdin with file name -
      # If so, break out of the while
      [ "$zipname" = '-' ] && break
      fileInFolder["$zipname"]="$sum"
      # Unzip file to stdout
      unzip -qqc -- "$zipname"
    done < <(md5sum --zero -- "$zipFolder/"*'.zip' </dev/null) | awk -f script.awk