Search code examples
bashshellglob

Test whether a glob has any matches in bash - with variables


I am trying the answer suggested in this question: Test whether a glob has any matches in bash

if test -n "$(find . -maxdepth 1 -name 'glob*' -print -quit)"
then
    echo found
else
    echo not found
fi

However, I am doing this in a script with variables.

#!/bin/sh
directory=~/nd
glob="*12*.idx"
cd $directory
if test -n "$(find . -maxdepth 1 -name \"$glob\" -print -quit)"
then
    echo found
else
    echo not found
fi

Running the script gives me:

not found

But running the command myself

find . -maxdepth 1 -name "*12*.idx" -print -quit

gives me a result

./notes_archive_2012.idx

Is this a quoting issue?


Solution

  • Yes, it is a quoting issue. The quotes should not be escaped inside $(...). Consider:

    test -n "$(find . -maxdepth 1 -name \"$glob\" -print -quit)" # Wrong
    

    In the above form, the argument to -name that find sees starts and ends with a literal double-quote. It would only match file names if the file names themselves began and ended with double-quotes.

    The following does what you want:

    test -n "$(find . -maxdepth 1 -name "$glob" -print -quit)" # Right
    

    From man bash:

    When using the $(command) form, all characters between the parentheses make up the command; none are treated specially.

    In other words, if you want a double-quote in a command inside $(...), just use a double-quote. The command inside $(...) should be written just as if it was entered on the command line by itself.