How to match nothing if a file name glob has no matches [duplicate]
Asked Answered
H

2

16

I want to loop over all files matching extension jpg or txt. I use:

for file in myDir/*.{jpg,txt}
do
  echo "$file"
done

Problem: If the directory contains no jpg file at all, the loop will have one iteration with output myDir/*.jpg. I thought * will be replaced by an arbitrary file (and if no file exists it cannot be expanded). How can I avoid the unwanted iteration?

Hie answered 3/4, 2015 at 18:53 Comment(2)
If a pattern has no matches, the default/POSIX behavior is to treat the pattern as a literal string, rather than ignoring or removing the pattern.Noreennorene
Unrelated to the question, but note that the braces are not part of the pattern. They are a bash shorthand for generating a set of related strings, and as such expand to the string myDir/*.jpg myDir/*.txt before pattern matching begins.Noreennorene
S
26

Use this to avoid the unwanted iteration:

shopt -s nullglob

From man bash:

nullglob: If set, bash allows patterns which match no files (see Pathname Expansion above) to expand to a null string, rather than themselves.

See: help shopt and shopt

Samp answered 3/4, 2015 at 18:56 Comment(0)
A
0

This and a duplicate question both were in context of not just pathname-expansion, but also brace-expansion, and a duplicate asked for POSIX.

The compgen -G does bash --posix compatible pathname-expansion (no brace-expansion) and... you guessed it: yields nothing if there are no matches.

Therefore write a bash --posix function to do it. Brief outline: temporarily use set -f to first do brace-expansion (without pathname-expansion) via an echo, then apply compgen -G to each result for pathname-expansion. Full function left as an exercise.

Absorbefacient answered 17/3, 2019 at 6:7 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.