Viorel
Viorel

Reputation: 1468

IFS in zsh behave differently than bash

foo() {
    local lines=$(ls -l)
    local IFS=$'\n'
    for line in $lines; do
        echo $line
    done
}

In zsh, the loop is only executed once, because the output for ls -l command is not split by new lines and the entire chunk of text is passed into $line. In bash though, works as intended. How can I have exactly same behaviour in both shells?

I'm not looking for an alternative solutions of looping over "ls" output. Just trying to understand why it's not working in zsh but works perfectly fine in bash. Instead of "ls" command can be anything else. e.g. "ps -a". The behaviour is the same. Output is not split by line.

Thanks!

Upvotes: 12

Views: 8604

Answers (1)

Dominik
Dominik

Reputation: 2541

ZSH does not split words by default (like other shells):

foo() {
    local lines=$(ls -l)

    local IFS=$'\n'
    if [ $ZSH_VERSION ]; then
      setopt sh_word_split
    fi

    for line in $lines; do
        echo line: $line
    done
}

foo

Credits go to @chris-johnsen with his answer. I support his argument to better use arrays (where possible):

local lines=("$(ls -l)")

Other options would be (ZSH only):

Upvotes: 18

Related Questions