如何避免在 zsh for-loop 中使用空格作为分隔符?

How to avoid using spaces as separators in zsh for-loop?

我正在尝试编写一个小脚本来转换音乐库中的一些文件。

但是如果我做类似的事情:

#!/usr/bin/zsh                                                                     

for x in $(find -name "*.m4a");
do
    echo $x;
done

在包含以下内容的文件夹中解释时:

foo\ bar.m4a

会 return :

foo
bar.m4a

如何防止 for 循环将 space 个字符解释为分隔符?

我可以将 $(find -name "*.m4a") 替换为 $(find -name "*.m4a" | sed "s/ /_/g"),然后在循环内以另一种方式使用 sed,但是如果文件 names/paths 已经包含下划线(或其他字符)怎么办我可以使用而不是下划线)?

有什么想法吗?

我知道了。

这里建议:https://askubuntu.com/questions/344407/how-to-read-complete-line-in-for-loop-with-spaces

我可以将 IFS(内部字段分隔符)设置为“\n”。

所以这行得通:

#!/usr/bin/zsh                                                                                          

IFS=$'\n'
for x in $(find -name "*.m4a");
do
    echo $x;
done

我希望这可以帮助其他人!

在这里使用 zsh 的 globbing 设施而不是 find

for x in **/*.m4a; do
    echo "$x"
done

zsh 的默认设置下,在循环主体中引用 $x 是可选的,但无论如何这样做并不是一个坏主意。

您可以通过双引号防止命令替换的分词:

#!/usr/bin/zsh                                                                     

for x in "$(find -name "*.m4a")"
do
    echo "$x"
done

请注意,命令替换内的双引号与外部的双引号不冲突(实际上我以前从未注意到这一点)。如果您觉得单引号更具可读性,您可以像 "$(find -name '*.m4a')" 一样轻松地使用单引号。无论如何,我通常使用带有 find 初选的单引号。

出于同样的原因,在循环体内引用也很重要。它将确保 x 的值作为单个参数传递。

但这绝对是一个混合的、弗兰肯斯坦式的解决方案。您最好使用 或使用 find,如下所示:

find . -name '*.mp3' -exec echo {} \;

但这种形式是有限的。您可以添加额外的 -exec 初选,它们将像 shell 命令一样执行,由 && 分隔,但您不能从一个 -exec 传送到另一个 -exec,您可以' 与 shell 交互(例如,通过分配或扩展参数)。