Test whether a glob has any matches in bash

后端 未结 19 2337
夕颜
夕颜 2020-11-22 15:51

If I want to check for the existence of a single file, I can test for it using test -e filename or [ -e filename ].

Supposing I have a glob

相关标签:
19条回答
  • 2020-11-22 16:41
    #!/bin/bash
    set nullglob
    touch /tmp/foo1 /tmp/foo2 /tmp/foo3
    FOUND=0
    for FILE in /tmp/foo*
    do
        FOUND=$((${FOUND} + 1))
    done
    if [ ${FOUND} -gt 0 ]; then
        echo "I found ${FOUND} matches"
    else
        echo "No matches found"
    fi
    
    0 讨论(0)
  • 2020-11-22 16:43

    The nullglob shell option is indeed a bashism.

    To avoid the need for a tedious save and restore of the nullglob state, I'd only set it inside the subshell that expands the glob:

    if test -n "$(shopt -s nullglob; echo glob*)"
    then
        echo found
    else
        echo not found
    fi
    

    For better portability and more flexible globbing, use find:

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

    Explicit -print -quit actions are used for find instead of the default implicit -print action so that find will quit as soon as it finds the first file matching the search criteria. Where lots of files match, this should run much faster than echo glob* or ls glob* and it also avoids the possibility of overstuffing the expanded command line (some shells have a 4K length limit).

    If find feels like overkill and the number of files likely to match is small, use stat:

    if stat -t glob* >/dev/null 2>&1
    then
        echo found
    else
        echo not found
    fi
    
    0 讨论(0)
  • 2020-11-22 16:47
    if ls -d $glob > /dev/null 2>&1; then
      echo Found.
    else
      echo Not found.
    fi
    

    Note that this can be very time cosuming if there are a lot of matches or file access is slow.

    0 讨论(0)
  • 2020-11-22 16:49

    Bash specific solution:

    compgen -G "<glob-pattern>"
    

    Escape the pattern or it'll get pre-expanded into matches.

    Exit status is:

    • 1 for no-match,
    • 0 for 'one or more matches'

    stdout is a list of files matching the glob.
    I think this is the best option in terms of conciseness and minimizing potential side effects.

    UPDATE: Example usage requested.

    if compgen -G "/tmp/someFiles*" > /dev/null; then
        echo "Some files exist."
    fi
    
    0 讨论(0)
  • 2020-11-22 16:49

    If you have globfail set you can use this crazy (which you really should not)

    shopt -s failglob # exit if * does not match 
    ( : * ) && echo 0 || echo 1
    

    or

    q=( * ) && echo 0 || echo 1
    
    0 讨论(0)
  • 2020-11-22 16:50

    I did not see this answer, so I thought I'd put it out there:

    set -- glob*
    [ -f "$1" ] && echo "found $@"
    
    0 讨论(0)
提交回复
热议问题