Bash – Expand shell variable without globbing

bashtestvariable substitutionwildcards

I want to check whether an input string refers to a file name – not a wildcard string like *.txt.

This doesn't work:

if [ -f "$1" ];

Because $1 gets expanded to *.txt, which gets expanded to, say foo.txt bar.txt, which gets passed to test -f.

Short of explicitly checking for wildcard characters, is there a general way to perform a shell substitution, and then prevent any globbing?

Best Answer

No, globs are not expanded when quoted, so:

set -- '*.txt'
[ -f "$1" ]

Will check whether the file called *.txt in the current directory is a regular file or a symlink to a regular file.

[ -f $1 ]

would be a problem ($1 would undergo word splitting (here not doing anything with the default value of $IFS) and filename generation).

If you wanted to check whether there were regular files with a .txt extension, you'd need a loop or use find or zsh glob qualifiers.

set -- *.txt
for f do
  if [ -f "$f" ]; then
    echo "there is at least one regular file with a .txt extension here"
  fi
done

Or if the pattern is found in $1:

IFS= # disable the globbing part of the split+glob operator
set -- $1
for f do... # as above

zsh:

files=(*.txt(N-.))
echo "$#files regular files with a .txt extension here"

find:

find -L . ! -name . -prune ! -name '.*' -name '*.txt' -type f | grep -q . &&
  echo there are regular .txt files in here
Related Question