0

Is there a way to use a Filename Expansion within a test expression, more specifically, a bash conditional expression?

For example:

[[ -f foo* ]] && echo 'found it!' || echo 'nope!';

... will output "nope!" either if the foobar file exists on the current directory or not.

And adding a var like...

bar=foo*
[[ -f `echo $bar` ]] && echo 'found it!' || echo 'nope!';

... will output "found it!" if the foobar file exists, but only if the echo $bar expansion returned only one file.

3

3 Answers 3

3

The following assume that you don't care whether the glob matches any files, including block special files, character special files, directories, symlinks, etc.

This is the ideal use case for failglob:

shopt -s failglob
if echo foo* &>/dev/null
then
    # files found
else
    # no files found
fi

Or, if you need the list of files if they exist:

shopt -s failglob
files=(foo*)
if [[ "${#files[@]}" -eq 0 ]]
then
    # no files found
else
    # files found
fi

If no files found is an error you could simplify this:

set -o errexit
shopt -s failglob
files=(foo*)
# We know that the expansion succeeded if we reach this line

Old answer

This might be a (rare!) legitimate use of ls in a script:

if ls foo* &>/dev/null
then
    …
else
    …
fi

Alternatively, find foo* -maxdepth 0 -printf ''.

0
0

Based on this answer, we can use shopt -s nullglob to ensure noting is returned if the directory is empty:

[[ -n "$(shopt -s nullglob; echo foo*)" ]] && echo 'found it!' || echo 'nope!';
2
  • 1
    You shouldn't use && and ||, just use an if construct, it's also not necessary to terminate the line with ;
    – jesse_b
    Aug 13, 2020 at 22:35
  • This does not seem to capture the fact that the question uses -f and not -e as the test operator. The test should be for regular files, not for existence.
    – Kusalananda
    Aug 14, 2020 at 5:42
0

For completeness' sake, here are some examples using find:

#!/bin/bash

term=$1

if find -maxdepth 1 -type f -name "$term*" -print -quit | grep -q .; then
    echo "found"
else
    echo "not found"
fi

if [ -n "$(find -maxdepth 1 -type f -name "$term*" -print -quit)" ]; then
    echo "found"
else
    echo "not found"
fi

And some tests:

user@host > find -type f
./foobar
./bar/foo
./bar/bar
./find_prefixed_files.sh
./ba
user@host > ./find_prefixed_files.sh foo
found
found
user@host > ./find_prefixed_files.sh bar
not found
not found

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.