TL, DR:
array_of_lines=("${(@f)$(my_command)}")
First mistake (→ Q2): IFS='\n'
sets IFS
to the two characters \
and n
. To set IFS
to a newline, use IFS=$'\n'
.
Second mistake: to set a variable to an array value, you need parentheses around the elements: array_of_lines=(foo bar)
.
This would work, except that it strips empty lines, because consecutive whitespace counts as a single separator:
IFS=$'\n' array_of_lines=($(my_command))
You can retain the empty lines except at the very end by doubling the whitespace character in IFS
:
IFS=$'\n\n' array_of_lines=($(my_command))
To keep trailing empty lines as well, you'd have to add something to the command's output, because this happens in the command substitution itself, not from parsing it.
IFS=$'\n\n' array_of_lines=($(my_command; echo .)); unset 'array_of_lines[-1]'
(assuming the output of my_command
doesn't end in a non-delimited line; also note that you lose the exit status of my_command
)
Note that all the snippets above leave IFS
with its non-default value, so they may mess up subsequent code. To keep the setting of IFS
local, put the whole thing into a function where you declare IFS
local (here also taking care of preserving the command's exit status):
collect_lines() {
local IFS=$'\n\n' ret
array_of_lines=($("$@"; ret=$?; echo .; exit $ret))
ret=$?
unset 'array_of_lines[-1]'
return $ret
}
collect_lines my_command
But I recommend not to mess with IFS
; instead, use the f
expansion flag to split on newlines (→ Q1):
array_of_lines=("${(@f)$(my_command)}")
Or to preserve trailing empty lines:
array_of_lines=("${(@f)$(my_command; echo .)}")
unset 'array_of_lines[-1]'
The value of IFS
doesn't matter there. I suspect that you used a command that splits on IFS
to print $array_of_lines
in your tests (→ Q3).
zsh
echo
behaves the standard way, like bash
in UNIX mode. That is it expands \b
to the ASCII BS character as the UNIX specification requires.
Don't use echo
to display arbitrary strings, use printf
:
printf '%s\n' "$1"
print -r -- "$1"
also works but is ksh
/zsh
specific.
echo -E - "$1"
work with zsh
and I believe some BSDs.
cat << EOF
$1
EOF
works in any Bourne-like shell even those from a few decades when there was no printf
command but it spawn a new process, and is really not necessary nowadays as we now have printf
everywhere.
And by the way, you need to escape backslashes on a shell command line as it's special to the shell (every shell but rc
), so:
$ foo '\\foo\bar'
foo \\foo\bar
would pass the "\foo\bar"
string to foo
which can't reinvent the lost backslash back.
Best Answer
You need to include the directory into the exception:
print -l foo/*~foo/type_A*
orprint -l foo/*~{foo/type_A*}
.If you want, you can replace the directory by a wildcard:
print -l foo/*~*/type_A*