Does ash have an equivalent to bash's 'nullglob' option?
Asked Answered
D

2

10

If a glob pattern doesn't match any files, bash will just return the literal pattern:

bash-4.1# echo nonexistent-file-*
nonexistent-file-*
bash-4.1#

You can modify the default behavior by setting the nullglob shell option so if nothing matches, you get a null string:

bash-4.1# shopt -s nullglob
bash-4.1# echo nonexistent-file-*

bash-4.1# 

So is there an equivalent option in ash?

bash-4.1# ash
~ # echo nonexistent-file-*
nonexistent-file-*
~ # shopt -s nullglob
ash: shopt: not found
~ # 
Dropkick answered 29/1, 2011 at 20:24 Comment(0)
T
7

For shells without nullglob such as ash and dash:

IFS="`printf '\n\t'`"   # Remove 'space', so filenames with spaces work well.

# Correct glob use: always use "for" loop, prefix glob, check for existence:
for file in ./* ; do        # Use "./*", NEVER bare "*"
    if [ -e "$file" ] ; then  # Make sure it isn't an empty match
        COMMAND ... "$file" ...
    fi
done

Source: Filenames and Pathnames in Shell: How to do it correctly (cached)

Tuppence answered 29/1, 2011 at 21:12 Comment(3)
I think you don't need to set IFS in this caseFuscous
This only works for globs that happen to match themselves. It's not a general replacement for nullglob.Colpotomy
It solved it with test "$(echo file-*)" = "file-*" && true || <something using files>Sickening
G
6

This method is more performant than checking existence every iteration:

set -- nonexistent-file-*
[ -e "$1" ] || shift
for filename; do
    echo "$filename"
done

We use set to expand the wildcard into the shell's argument list. Note this will overwrite any positional arguments ($1, $2, ...) originally passed to the script. The special argument -- makes it work even if the glob pattern would start with a + or - character that could conflict with other set usages otherwise.

If the first element of the argument list does not exist, the glob didn't match anything. Unlike comparing the first result with the verbatim glob pattern, this works correctly even if the glob's first match was on a filename identical to the glob pattern.

In case of no match, the argument list contains a single element, and we shift it off, so that the argument list is now empty. Then the for loop will not perform any iterations at all.

Otherwise, we loop over the list of arguments which the glob expanded into, using the implicit behavior of for when there is nothing after the variable name (being equivalent to in "$@", iterating through all positional arguments).

Gomphosis answered 20/1, 2017 at 4:8 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.