Reputation: 10685
Following what I found here, I tried to split the list of files of a certain pattern to an array. However, the string doesn't split (The empty line is just to ease on the reading).
bash-3.2$ files=jfn240_463.o*
bash-3.2$ echo $files
jfn240_463.o9017306 jfn240_463.o9075989 jfn240_463.o9281439 jfn240_463.o9287196
bash-3.2$ IFS=' ' read -ra ll <<< $files
bash-3.2$ echo $ll
jfn240_463.o9017306 jfn240_463.o9075989 jfn240_463.o9281439 jfn240_463.o9287196
bash-3.2$ IFS=' ' read -ra ll <<< "$files"
bash-3.2$ echo $ll
jfn240_463.o9017306 jfn240_463.o9075989 jfn240_463.o9281439 jfn240_463.o9287196
bash-3.2$ echo ${ll[@]}
jfn240_463.o9017306 jfn240_463.o9075989 jfn240_463.o9281439 jfn240_463.o9287196
bash-3.2$ echo ${ll[1]}
bash-3.2$
I was sure I would get an array, so why won't I?
Edit:
I tried to use find
instead without much success.
bash-3.2$ files=$(find jfn240_463.o*)
bash-3.2$ echo ${files[0]}
jfn240_463.o9017306 jfn240_463.o9075989 jfn240_463.o9281439 jfn240_463.o9287196
bash-3.2$
bash-3.2$ IFS=' ' read -ra ll <<< $files
bash-3.2$ echo ${ll[@]}
jfn240_463.o9017306
bash-3.2$
Upvotes: 1
Views: 150
Reputation: 241881
Ignacio Vazquez-Abrams has the problem precisely correct: when you define:
$ files=jfn240_463.o*
the shell does not expand the *
("pathname expansion"). When you write:
$ echo $files
the shell does expand the *
. To see the real value of $files
, you need to write:
$ echo "$files"
jfn240_463.o*
So $files
does not have a space in it.
You might expect the same to apply to <<<
, but it turns out that bash does not distinguish between <<<$files
and <<<"$files"
, because bash does not do pathname expansion on the word following <<<
. You can see this by typing, for example:
$ cat <<<jfn240_463.o*
jfn240_463.o*
(There is actually a small difference between <<<$files
and <<<"$files"
. Bash performs parameter expansion, command expansion and arithmetic expansion on the word following <<<
, in this case $files
. If the word is not quoted, it also performs word-splitting. However, after the word-splitting is finished, the words are joined together again, separated by a single space. Consequently, in the unquoted case, all sequences of whitespace are reduced to a single space, whereas in the quoted case the white space is retained precisely. The difference is most visible when $IFS
has been changed to something other than whitespace.)
There are various possible workarounds, of which the simplest is to simply set the array directly, as Ignacio Vasquez-Abrams suggests:
ll=(jfn240_463.o*)
(In this syntax, bash does perform pathname expansion.)
However, that will fail if any file has whitespace in its name. Another simple solution (with bash), if no file has a newline in its name, is to use mapfile:
mapfile -t ll < <(ls jfn240_463.o*)
or, with the bash builtin printf:
mapfile -t ll < <(printf "%s\n" jfn240_463.o*)
It's by no means simple to get this to work in the case where a filename might contain arbitrary characters (other than \0
and /
, which cannot appear in filenames).
Upvotes: 0
Reputation: 799150
The problem is that $files
contains "jfn240_463.o*"
and not a bunch of filenames delimited by spaces. You can't split that by a space since there's no space even in it. Use an array in the first place:
ll=(jfn240_463.o*)
Upvotes: 2