Is there an easy way to set nullglob for one glob

前端 未结 5 1084
谎友^
谎友^ 2021-02-03 23:22

In bash, if you do this:

mkdir /tmp/empty
array=(/tmp/empty/*)

you find that array now has one element, \"/tmp/empty/*\"

相关标签:
5条回答
  • 2021-02-03 23:59

    This is the simplest solution I've found:

    For example, to expand the literal **/*.mp3 into a glob for only a particular variable, you can use

    VAR=**/*.mp3(N)
    

    Source: https://unix.stackexchange.com/a/204944/56160

    0 讨论(0)
  • 2021-02-04 00:01

    With mapfile in Bash 4, you can load an array from a subshell with something like: mapfile array < <(shopt -s nullglob; for f in ./*; do echo "$f"; done). Full example:

    $ shopt nullglob
    nullglob        off
    $ find
    .
    ./bar baz
    ./qux quux
    $ mapfile array < <(shopt -s nullglob; for f in ./*; do echo "$f"; done)
    $ shopt nullglob
    nullglob        off
    $ echo ${#array[@]}
    2
    $ echo ${array[0]}
    bar baz
    $ echo ${array[1]}
    qux quux
    $ rm *
    $ mapfile array < <(shopt -s nullglob; for f in ./*; do echo "$f"; done)
    $ echo ${#array[@]}
    0
    
    • Be sure to glob with ./* instead of a bare * when using echo to print the file name
    • Doesn't work with newline characters in the filename :( as pointed out by derobert

    If you need to handle newlines in the filename, you will have to do the much more verbose:

    array=()
    while read -r -d $'\0'; do
        array+=("$REPLY")
    done < <(shopt -s nullglob; for f in ./*; do printf "$f\0"; done)
    

    But by this point, it may be simpler to follow the advice of one of the other answers.

    0 讨论(0)
  • 2021-02-04 00:12

    Unset it when done:

    shopt -u nullglob
    

    And properly (i.e. storing the previous state):

    shopt -u | grep -q nullglob && changed=true && shopt -s nullglob
    ... do whatever you want ...
    [ $changed ] && shopt -u nullglob; unset changed
    
    0 讨论(0)
  • 2021-02-04 00:20

    This may be close to what you want; as is, it requires executing a command to expand the glob.

    $ ls
    file1 file2
    $ array=( $(shopt -s nullglob; ls foo*) )
    $ ls foo*
    ls: foo*: No such file or directory
    $ echo ${array[*]}
    file1 file2
    

    Instead of setting array in the subshell, we create a subshell using $() whose output is captured by array.

    0 讨论(0)
  • 2021-02-04 00:25

    This is just a tiny bit better than your original suggestion:

    local nullglob=$(shopt -p nullglob) ; shopt -s nullglob
    

    ... do whatever you want ...

    $nullglob ; unset nullglob
    
    0 讨论(0)
提交回复
热议问题