Reputation: 1468
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
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):
local lines=("${(f)$(ls -l)}")
, where (f)
is shorthand for (ps:\n:)
for line in ${=lines}; do
(note the added equal sign)Upvotes: 18