Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

IFS in zsh behave differently than bash

Tags:

bash

zsh

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!

like image 301
Viorel Avatar asked Dec 25 '16 09:12

Viorel


People also ask

How does zsh differ from bash?

Key Differences Between Zsh and Bash Zsh is more interactive and customizable than Bash. Zsh has floating-point support that Bash does not possess. Hash data structures are supported in Zsh that are not present in Bash. The invocation features in Bash is better when comparing with Zsh.

Do bash scripts work in zsh?

The ZSH shell is an extended version of the Bourne Again Shell; thus, most commands and scripts written for bash will work on ZSH. The ZSH shell provides full programming language features such as variables, control flow, loops, functions, and more.

Should I use zsh or bash on Mac?

The Z shell (also known as zsh ) is a Unix shell that is built on top of bash (the default shell for macOS) with additional features. It's recommended to use zsh over bash . It's also highly recommended to install a framework with zsh as it makes dealing with configuration, plugins and themes a lot nicer.

Is bash faster than zsh?

According to my tests, ksh is the winner and zsh is the runner-up. Both shells are 2–30 times faster than bash depending on the test. If you use bash for less than 100 lines as Google Shell Style Guide suggests, then I don't think you will notice the difference. Although it will of course depend on the task.


1 Answers

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):

  • local lines=("${(f)$(ls -l)}"), where (f) is shorthand for (ps:\n:)
  • for line in ${=lines}; do (note the added equal sign)
like image 134
Dominik Avatar answered Oct 12 '22 21:10

Dominik