Why do I need to care about `$IFS` when `read`-ing into a single variable?

A construction similar to IFS= read -r var is often seen as a "canonical" way in Bash to read a line of input into a variable (e.g. on unix.SE).

It is clear enough why setting an empty $IFS might be beneficial in general, that is, to control (prevent) word splitting. However, I’m having trouble understanding why specifically is that needed when reading into a single variable? The bash manual says:

If there are more words than names, the remaining words and their intervening delimiters are assigned to the last name

So, even without changing IFS, if read is passed a single variable, then shouldn’t it end up saving the entire line into that variable, as desired? What is the reason for setting an empty $IFS in this case?

Asked By: intelfx

||

Consider this example (unsetting $IFS so that the default value is used):

$ unset IFS
$ IFS= read -r foo <<<" a "
$ printf "%qn" "$foo"
 a
$ read -r foo <<<" a "
$ printf "%qn" "$foo"
a

Or when it contains a different value (in bash or other POSIX-like shells other than zsh):

$ IFS=:
$ IFS= read -r foo <<< "a:"
$ printf "%qn" "$foo"
a:
$ read -r foo <<< "a:"
$ printf '%qn' "$foo"
a

This case is covered in the post mentioned in the question (emphasis added):

Now if passed only one argument, that doesn’t become read line. It’s still read remaining_words. Backslash processing is still done, IFS whitespace characters¬≤ are still removed from the beginning and end.

Answered By: muru
Categories: Answers Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.