Bash – understanding the default value of IFS

bashquotingshell

In my GNU bash version 4.2.8, IFS has a default value of space, tab and line feed by default:

usr@T42 ~ $ echo -n "$IFS" | hexdump -C
00000000  20 09 0a                                          | ..|
00000003
usr@T42 ~ $ 

Is there a reason for such default IFS? In addition, which utilities use IFS besides bash built-in read?

Best Answer

The IFS variable is used every time the shell performs a task called word splitting. The most common cases where this is used is after parameter expansion (eg $var) or command substitution (eg $(some-command) or the deprecated backticks) in a command. Here if the expansion contains any IFS characters, then it split into different 'words' before the command is processed. Effectively this means that these characters split the substituted text into different arguments (including the name of the command if the variable is specified first).

Thus the reason for the default value of IFS being space, tab and newline is that these are the whitespace characters that would normally be expected to split a word.

One way to prevent word splitting from happening is to use double quotes around the expansion ("$var") - in fact you have done this in your question. If you didn't do this there would be no output from echo as it would have no arguments, only characters splitting arguments.

Note also that two places where word splitting doesn't happen after parameter expansion are with variable assignment (eg var=$othervar and var=$(somecommand) is ok), and within the [[ ]] construct ([[ $var = $othervar ]] is ok, but [ $var = $othervar ] should be quoted).

Finally, as a wise man once pointed out to me, a common misconception is that prevention of word splitting is the only reason to quote a variable. It isn't, the quoting also prevents pathname expansion or glob expansion as it is more commonly known. If a variable contains glob characters like * then these may be expanded into filenames when the variable is used unquoted in a command. Eg, consider:

var=*
echo $var

This will display the names of the files in the current directory.

As Stephane points out below, the order of characters within IFS is significant when expanding "$*". From the bash man page:

"$*" is equivalent to "$1c$2c...", where c is the first character of the value of
the IFS variable.  If IFS is unset, the parameters are separated by spaces.  If
IFS is null, the parameters are joined without intervening separators.

For more examples of word splitting, please see this answer - https://unix.stackexchange.com/a/118444/48083

Related Question