Yes, PATH
can contain newlines (even on ancient Unix system).
As to splitting any string in shell, the only way you can do it portably is with IFS
. You can use IFS=:; set -f; set -- $PATH
or pass it to a function instead of looping with for
, though.
With bash
you can also "read" a string into an array:
xtra=$'some\nother\nplace\n\n'; PATH="$PATH:$xtra"
mapfile -td: path < <(printf %s "$PATH")
printf '<%s>\n' "${path[@]}"
But using arrays is usually not a good idea, because they can't be stored transparently in environment variables or passed as a single argument to external commands.
Notice that IFS
will terminate fields, not separate them (kind of like \n
at the end of the file won't be treated like an empty line by programs reading the file line-by-line); if that's not what's expected, and you really want to create an extra empty field at the end when splitting a string that ends in a character from IFS
, you should join an empty string after the variable that is subject to word splitting:
(P=/bin:; IFS=:; printf '<%s>\n' $P"")
</bin>
<>
The word splitting algorithm will also ignore white space characters at the beginning of the string, if those whitespace characters are part of IFS
. If you want an extra field for the leading whitespace, you should also join an empty string before the variable:
(P=' foo : bar '; IFS=': '; set -f; set -- $P; printf '<%s>\n' "$@")
<foo>
<bar>
(P=' foo : bar '; IFS=': '; set -f; set -- ""$P""; printf '<%s>\n' "$@")
<>
<foo>
<bar>
<>
/bin::/usr/bin
would be split into/bin
and/usr/bin
instead of/bin
,""
and/usr/bin
. – Stéphane Chazelas Dec 31 '18 at 11:12