0

Terdon's Example 3 from https://unix.stackexchange.com/a/612718/182280:

  1. Select all files except those whose names end in .sh or .jkl

    $ shopt -s extglob nullglob
    $ files=(!(*.sh|*.jkl))
    $ echo "${files[@]}"
    file.abc file.ABC file.def file.ghi
    

The challenge is a space in the file causes failures in the script:

for f in ${files[*]}  #https://unix.stackexchange.com/q/278502/182280
do
 echo "Processing $f file... "
done

For example, the space in the file fi le1.jkl "breaks" the file when processed by the script and returns:

 processing `fi` file...
 processing `le1.jkl` file...

What can be done to ensure that spaces do not "break" the file name?

Comments that serve to clarify the context / questions are appreciated.

gatorback
  • 1,384
  • 23
  • 48

1 Answers1

12

See the comment on the question the loop came from: you should use "${files[@]}" instead of ${files[*]}. This will ensure that each entry in the array is quoted correctly, and processed as a whole by for:

for f in "${files[@]}"
do
 echo "Processing $f file... "
done

See the Bash manual section on arrays for details:

Any element of an array may be referenced using ${name[subscript]}. The braces are required to avoid conflicts with the shell’s filename expansion operators. If the subscript is ‘@’ or ‘*’, the word expands to all members of the array name. These subscripts differ only when the word appears within double quotes. If the word is double-quoted, ${name[*]} expands to a single word with the value of each array member separated by the first character of the IFS variable, and ${name[@]} expands each element of name to a separate word.

See also What is the difference between $* and $@?

Stephen Kitt
  • 434,908