Skip to content
Advertisement

How to use content of variable in bash to pass to find in script?

In a bash script I’m trying to use the content of a variable to be used as options for the find command:

#!/bin/bash
FILE_EXTENSIONS=( txt png jpg )

FIRST=1
for FILE_EXTENSION in ${FILE_EXTENSIONS[@]} 
do
#   echo "$FILE_EXTENSION"
    if [[ $FIRST == 1 ]]
    then
        FIND_FILTER="-iname '*.$FILE_EXTENSION'"
        FIRST=0
    else
        FIND_FILTER="${FIND_FILTER} -o -iname '*.$FILE_EXTENSION'"
    fi
done
# Read and write only for user and group, ignore case '-iname'
#find . -type f "$FIND_FILTER" -exec chmod 660 {} ;
echo Find filter: $FIND_FILTER
# This might work with some already provided suggestions:
find . -type f $FIND_FILTER
# But this fails so far
find . -type f $FIND_FILTER -exec chmod 660 {} ;        
#EOF

The aim is to set proper access rights as for what ever reason quite some files (such as pictures or office documents) are marked executable.

So in reality the script above has several arrays with file extensions concatenated, but the script shows the problem.

The first approach would have been to iterate over the final array and call find each time. But from a runtime point of view it would be stupid to search each time over and over again.

I also could simply do this in python but for once I thought I would like to solve it with linux basic means in bash.

It looks like the content of the FIND_FILTER variable is correct (at least what is printed with echo) but then … it doesn’t work.

Any suggestions what is going wrong?

Advertisement

Answer

You started using arrays (nearly) correctly, but then abandoned them for a space-separated string. Keep using arrays.

  1. Always quote the expansion of an @-indexed array; otherwise, there is no reason to use @ over *.
  2. As a general rule, avoid all-caps variables names; they are (mostly) reserved for use by the shell.
  3. Enclose the filters joined by -o in escaped parentheses so that find treats them as a single condition to be met in addition to the -type primary.
  4. Use -exec ... + so that chmod can operate on multiple files per call, rather than calling it once for each file separately.

#!/bin/bash
file_extensions=( txt png jpg )

first=1
for ext in "${file_extensions[@]}"
do
#   echo "$ext"
    if [[ $first == 1 ]]
    then
        find_filter=(-iname "*.$ext")
        first=0
    else
        find_filter+=( -o -iname "*.$ext")
    fi
done


# Read and write only for user and group, ignore case '-iname'
find . -type f ( "${find_filter[@]}" ) -exec chmod 660 +
User contributions licensed under: CC BY-SA
5 People found this is helpful
Advertisement