IFS and Z-Shell

Nothing inspires a short blog writing like the “Eureka!” moment you get when something which was evading you clicks into place.

I’ve been using Z-Shell for a while now as my primary shell of choice. However, I usually write my shell scripts in Bash.

Occasionally I come across a situation where I have a shell command which needs to execute in both Bash and Z-Shell. This is when you realise that despite the similarity of the two shells, they’re subtly different beasts.

Consider this really simple snippet of code, which does three things:

  1. Sets a list of semicolon separated values in a string.
  2. Sets the IFS variable as a semicolon.
  3. Iterates over the items of the semicolon separated values and prints each one on its own line.

In Bash:

bash-3.2$ test='alpha;bravo;charlie;delta'
bash-3.2$ IFS=';'
bash-3.2$ for item in $test; do echo ">>> $item"; done
>>> alpha
>>> bravo
>>> charlie
>>> delta

But in Z-Shell it doesn’t work:

$ echo $SHELL
$ test='alpha;bravo;charlie;delta'
$ IFS=';'
$ for item in $test; do echo ">>> $item"; done
>>> alpha;bravo;charlie;delta

So, what’s going on? Why does Z-Shell ignore the IFS variable? Well, the answer is that it behaves this way by default for reasons I’m not entirely clear on. My guess is it’s because Z-Shell supports native arrays, which Bash doesn’t. Therefore the assumption was probably made that you’d use Z-Shell’s far more robust array support than the old-skool approach of splitting strings.

But, there’s a workaround (isn’t there always?). You need to enable string splitting manually with setopt, which the following one-liner will achieve regardless of which shell you run it in:

setopt SH_WORD_SPLIT 2>&1; IFS=';'

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

Powered by WordPress.com.

Up ↑

%d bloggers like this: