AdVocem
AdVocem

Reputation: 58

How to put custom function's output into find utility as an option?

I want to send a list of extensions as a parameter. So I wrote a small helper function that parses a string of extensions and formats it in a way that "find" utility expects:

exts="txt log";
track=0;
function ext_parse()
{
for i in $exts; do
  if [[ $track -eq 0 ]]
  then
    varstr="-iname \"*.$i\"";
    track=1;
  else
    varstr="$varstr -o -iname \"*.$i\" ";
  fi
done
echo "$varstr";
}

So it returns:

-iname "*.txt" -o -iname "*.log" 

If I put this into "find" directly it works well:

find . -type f \( -iname "*.txt" -o -iname "*.log" \) -print

But any attempt to substitute this string with the function above that I've tried fails.

Is there any way to obtain that behavior or it is impossible by design?

Upvotes: 1

Views: 40

Answers (1)

gniourf_gniourf
gniourf_gniourf

Reputation: 46853

I would argue it's cleaner, safer and easier to use arrays:

ext_parse() {
    local i
    varstr=()
    for i; do
        ((${#varstr[@]}!=0)) && varstr+=( -o )
        varstr+=( -iname "*.$i" )
    done
}

To use this function, you would first call it with appropriate arguments, e.g., ext_parse txt log; this will set the array varstr; and then you can use it as:

find -type f \( "${varstr[@]}" \)

So your workflow looks like this:

$ ext_parse txt log
$ find -type f \( "${varstr[@]}" \)

RE: your comment: to clarify your worry about find being run once per element in array (which is wrong!), do the following test: save the following script as banana:

#!/bin/bash

for ((i=1;i<=$#;++i)); do
    printf 'Argument %d: %s\n' "$i" "${!i}"
done

Then chmod +x banana, and try it:

$ ext_parse txt log
$ ./banana -type f \( "${varstr[@]}" \)
Argument 1: -type
Argument 2: f
Argument 3: (
Argument 4: -iname
Argument 5: *.txt
Argument 6: -o
Argument 7: -iname
Argument 8: *.log
Argument 9: )

So you can see that banana is executed once only, with all the arguments given above: exactly what you want!

Upvotes: 1

Related Questions