Linux/Unix: Understanding IFS (Input Field Separators)📄 BetterWays.dev wiki page | 🕑 Last updated: Dec 22, 2022
IFS is a special shell variable that specifies the characters that will be used as field separators.
Its default value is usually a combination of three whitespace characters: space, tab, and newline.
Printing these characters to the shell output can be a bit tricky, but here are a few examples:
printf %s "$IFS" | od -c printf %q "$IFS" printf %s "$IFS" | cat -A cat -etv <<<"$IFS"
(the first way is the most portable one, others won't necessarily work in all environments)
We can also get the value from the output from the set command:
set | grep -w IFS=
Typically, you'll see something like this:
How does IFS work?
Let's define a simple shell variable, named
If we try to echo it:
echo "$v" echo $v
The result in both cases looks the same as our original value:
a b:c a b:c
But let's see what happens if we change the IFS variable to the colon character:
Note: whenever you're changing IFS for the entire process, it's a good idea to save the old value, so you can reverse it easily.
Let's try to run the same command again:
echo "$v" echo $v
The output of the first command is still the same, but the second one looks different:
a b:c a b c
In the first case,
echo gets a single argument - full value of the variable
v, but in the second one, the shell parses that value into the list of arguments, using the IFS variable as a separator.
Note: Splitting of unquoted variables is the default behavior in
zsh you can enable it with
To understand this better, let's see what individual arguments look like:
set -- $v echo $1 echo $2
We're using the
set command to set the positional arguments ($1, $2, $3, etc.) from our
As we can see, the standard whitespace separator is now part of the first argument, and the colon character has been used as a separator between arguments:
a b c
If we go back to the original IFS value:
IFS=OLDIFS set -- $v echo $1 echo $2
The standard whitespace is used as a separator:
As we've seen before, the default IFS is a sequence of whitespace characters, so let's try to append it with a colon character:
IFS="$OLDIFS:" set -- $v echo $1 echo $2 echo $3
a b c
Once you understand how IFS works, it can be quite handy, especially in combination with positional arguments. For example, since the
for loop by default uses positional arguments, we can now iterate over the previously set arguments (with the
set command) simply by doing this:
for i; do echo $i; done
a b c
In the past, the IFS variable was normally inheritable by the subprocesses, but this has been restricted on pretty much every modern UNIX due to security reasons (for example, programs could be tricked to execute different binaries by setting IFS to "/").
For example, executing something like
IFS=: bash -c 'printf %q "$IFS"' will result in the default IFS value:
Ask me anything / Suggestions
If you find this site useful in any way, please consider donating. I'm trying to keep it as clean and fast as possible - there are no ads, no affiliate links, and no analytics/tracking scripts.