Before I answer, here's a warning: changing IFS
tends to have really confusing effects. There are a few places where it's relatively safe and has well-defined effects (like setting it for the read
command, as in IFS= read -r line
and IFS=, read -r field1 field2 field3
), but trying to understand its behavior in general is, in my opinion, more work than it's worth. Also, if you do change it, either isolate it to a particular command by doing the assignment as a prefix to the command (again, as in IFS= read -r line
) or by setting it back to normal as soon as possible after whatever you need to change it for.
Now to the question: these aren't good examples of IFS
effects, first because $*
expands to the current argument list, and interactive shells don't generally have arguments, so it's going to expand to the empty string. You can change that with the set
command if you want. Here's an example:
$ echo "$*"
$ set -- "foo bar" "baz/quux"
$ echo "$*"
foo bar baz/quux
Second, because changing IFS
as a prefix to a particular command (as in IFS= echo "$*"
) only affects the command as it runs, not while the shell is expanding its arguments (which happens before the command itself runs), and echo
itself isn't affected by IFS
(it always sticks its arguments together with spaces, no matter what IFS
is set to). For example:
$ IFS= echo "$*" # No effect, because IFS is only set for echo, which ignores it
foo bar baz/quux
Contrast that with setting IFS
for the shell itself:
$ saveIFS=$IFS # Save the normal IFS, so we can set it back later
$ IFS= # Set IFS for the entire shell
$ echo "$*" # Now we'll see an effect
foo barbaz/quux
$ IFS='+-*/' # Let's try another value
$ echo "$*" # Now the arguments get merged, first char of IFS beween them
foo bar+baz/quux
$ echo $* # See below
foo bar baz quux
$ printf '%s\n' $* # See below
foo bar
baz
quux
$ IFS=$saveIFS # Set it back to normal, to avoid trouble later
So what happened with echo $*
when IFS
was "+-*/"? Well, IFS
is used both to merge and split arguments, so just like with echo "$*"
, the $*
bit expanded to foo bar+baz/quux
, but then since it wasn't double-quoted it then immediately got split into words (using all of the characters in IFS
), so it got split into three arguments to echo
: "foo bar" "baz", and "quux", and echo
then stuck those all together with spaces in between. Essentially the same thing happens with the printf
command, except the format string makes it print each following argument on a separate line, so you can see that "foo bar" is just one argument.
BTW, some people use the saveIFS
approach like I used here, some prefer to unset IFS
afterward, which makes the shell act as if IFS
was back to its normal space-tab-newline value. Both work, but not together. If you unset IFS
, and then later try to save & restore it, it'll come out set to the empty string, and things will be weird. You could also explicitly reset it with IFS=$' \t\n'
, but that's not portable to all shells (and will cause really weird effects in shells that don't support $' '
). Sigh.
EDIT: See this question for more options & discussion of how to save & restore the value of IFS
.
BTW2, in most situations you don't want the arguments either merged or split, so what you want is "$@"
. Unlike $*
, $@
doesn't merge the arguments, and with double-quotes it doesn't split them either (or expand them as filename wildcards) -- it just passes them straight through. But don't use args="$@"
, because that actually does merge them like "$*"
(or maybe with " " instead of the first char of IFS
, depending on the shell) (it has to merge them to save them in a plain variable). Use args=("$@")
instead, to save them as an array.
"$*"
expands to nothing, and second because usingIFS=something
doesn't affect how that command's arguments (like"$*"
) are expanded, it only takes effect on the command as it runs, andecho
isn't affected byIFS
. – Gordon Davisson Mar 19 '21 at 05:58"$*"
joins the positional parameters with SPC regardless of the value of$IFS
. The joining with the first character of$IFS
is a Korn shell invention. – Stéphane Chazelas Mar 19 '21 at 07:17SPC bash
didn't give me a clear interpretation. – variable_expander Mar 19 '21 at 07:23