0

I would like to determine an action by the file extension of files in my array. For example, if the array match *.zip then do x. The script will not be located in the archive path.

archive_path="$HOME/Downloads/"

compressed_files=("`find "$achieve_path" -iname "*.zip" -o -iname "*.rar" -o -iname "*.7z"`")

for files in "${compressed_files[@]}"; do
   echo "$files" ;

done

Update 1: This is another method that i tried. Returns no error, but also no results.

shopt -s nocasematch

dir="$HOME/Downloads/all/"

 for file in "$dir*.@(.zip|.rar|.7z)" ; do

   case "$file" in

  *.rar)
    echo "$file this is a rar file"
    ;;
  *.zip)
    echo "$file this is a zip file"
    #...
    ;;
  *.7z)
    echo "$file this is a 7z file"
    #...
    ;;
esac

done

Solution:

Tested Platforms: macOS Catalina

Notes: Upgrade your bash to the latest version, the latest macOS doesn't ship with the latest version of bash by default.

#!/usr/bin/env bash


shopt -s nocasematch

dir="$HOME/Downloads/all/"

 for file in "$dir"* ; do

   case "$file" in

  *.rar)
    echo "$file this is a rar file"
    ;;
  *.zip)
    echo "$file this is a zip file"
    #...
    ;;
  *.7z)
    echo "$file this is a 7z file"
    #...
    ;;
esac

done
Adrian
  • 33
  • 7
  • See https://stackoverflow.com/questions/23356779/how-can-i-store-the-find-command-results-as-an-array-in-bash. – rtx13 Apr 07 '20 at 13:52
  • 1
    The best, sound and foolproof way to execute something on the found files is using the `-exec` option of `find`. But we'd need what you want to do to help you further. – Quasímodo Apr 07 '20 at 14:11
  • 1
    You are creating an array with exactly one element, not an array with one file name per element. – chepner Apr 07 '20 at 14:15
  • `for file in "$dir"* ; do` The `'*'` must not be quoted or it will prevent expansion. You don't need anything else except the `case ... esac` which can handle the extensions. – David C. Rankin Apr 08 '20 at 07:46
  • many thanks David C. Rankin , it worked! – Adrian Apr 08 '20 at 07:56
  • Glad it worked. Those quoting rules get you every once in a while. If you paste your code in [Shellcheck.net](https://www.shellcheck.net/) it will find 99% of the problems in your script and offer fixes -- really nice tool. – David C. Rankin Apr 08 '20 at 08:01
  • thank you David, as a newbie i will def need it ! – Adrian Apr 08 '20 at 08:06

2 Answers2

0

See How can I store the "find" command results as an array in Bash for how to correctly pass the results of find into a bash array.

You can match in the for loop like this:

shopt -s nocasematch  # ignore upper/lower case in 'case' statement
for file in "${compressed_files[@]}" ; do
   case "$file" in
   *.zip)
      echo "do something with zip file $file"
      ;;
   *.rar)
      echo "do something else with rar file $file"
      ;;
   *)
      echo "handling file $file"
      ;;
   esac
done
rtx13
  • 2,580
  • 1
  • 6
  • 22
  • thank you for your answer @rtx, it works, but only has an effect on the last file in the array. on mac – Adrian Apr 07 '20 at 15:18
0

Unless you are stuck using an ancient version of bash, you don't need find here at all.

shopt -s globstar extglob nullglob nocasematch

for file in **/*.@(zip|rar|7z); do
     case $file in
       *.zip) ... ;;
       *.rar) ... ;;
       *.7z) ... ;;
     esac
done
chepner
  • 497,756
  • 71
  • 530
  • 681
  • thank you for your response, can you please clarify "for file in **/*.@(zip|rar|7z); do" and how do i reference the path to the compressed files? – Adrian Apr 08 '20 at 06:54
  • `file` is the path. `@(zip|rar|7z)` is an extended glob that matches either `zip`, `rar`, or `7z`. – chepner Apr 08 '20 at 11:32
  • thank you. ended up using this (in another type of script) : for file in "${home_dir}"**/*.@(rar|7z) ; do – Adrian Apr 08 '20 at 12:49