Question

I want to dynamically construct a "find" command and see whether it returns anything.

This is the minimised example. In a directory containing files,

find . -name '*'

of course returns the files. But

VAR="find . -name '*'"
$VAR

returns nothing. Looks like a problem of interpretation of quotes. But why?

(The real case is that I want to see whether files with a certain prefix exist. So I intended to use -name '${MYPREFIX}*', capture the output within $(), and test whether the resulting string is empty.)

Apologies if this is trivial. I did spend time to find the answer, but all cases I found were somehow different. Usually, the problem is the shell expanding the wildcard when the find command should do it. Here, the shell does not do any premature expansion, but neither does find, maybe because find receives literal quotes? Thanks for any insight.

Was it helpful?

Solution

eval $VAR

The eval will reinterpret the value of $VAR as a command with arguments.

Be wary: eval is a powerful but dangerous mechanism.

OTHER TIPS

I recommend against using eval whenever possible. In this case, if you really need to store the command in a variable before executing it, I'd recommend using an array and then invoking it as "${cmd_array[@]}":

var=(find . -name "${prefix}*")  # This stores the elements of the command as an array
result=$("${var[@]}")  # This executes the command and stores its output in $result

Note that you can also construct the find command dynamically:

patterns=()  # start with an empty list of patterns
for prefix in $prefix_list; do
    patterns+=(-o -name "${prefix}*")  # add each prefix to a list of find patterns
done
patterns=("${patterns[@]:1}") # Use array slicing to remove the first "-o"
result=$(find . "${patterns[@]}")

Depending on how you use it, it might also help to wrap the find command in a bash function:

find_prefix() {
    find . -name "${1}*"
}
result=$(find_prefix "$prefix")
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top