Bri*_*sen 3 bash macintosh read
我有这个脚本:
#!/bin/bash
function main {
while read -r file; do
do_something "$file"
done <<< $(find . -type f 2>/dev/null)
}
function do_something{
echo file:$@
}
Run Code Online (Sandbox Code Playgroud)
在 Linux 上,它工作正常,但在 Mac(Bash 版本 5.2)上,它将找到的所有文件视为一项,并将整个字符串不带换行符传递到do_something
. 如果我运行这个:
while read -r file; do
echo file:"$file"
done <<< $(find . -type f 2>/dev/null)
Run Code Online (Sandbox Code Playgroud)
直接在 Mac 上的 Bash 终端中也可以正常工作。那么出了什么问题呢?
在旧版本的 bash 中,<<< $param$((arith))$(cmdsubst)
where<<<
是从 zsh 复制的这里字符串运算符,此类未加引号的扩展会受到$IFS
-splitting 的影响,并且生成的单词会与空格连接起来,并将结果存储在构成重定向目标的临时文件中。
这个问题在 4.4 中得到了修复。请参阅CWRU/changelog 中的相应条目:
2015-09-02
redir.c
- write_here_string:不要对此处字符串文档进行分词。bash 文档总是说这种情况不会发生,尽管 bash 多年来一直这样做,并且实现此处字符串的其他 shell 不执行任何分词。实际效果是 IFS 字符序列被折叠为空格。修复了 Clint Hepner <clint.hepner@gmail.com> 报告的错误
但 macOS 仍然使用古老版本的 bash。您可能在其他地方安装了较新的 bash,但据我所知,您的 shebang 中使用的 /bin/bash 是 3.2.x,而不是 5.2。
虽然引用 the$(find...)
可以解决该特定问题,但这里迭代 的输出绝对是错误的方法find
。
请参阅为什么循环查找输出的输出是不好的做法?
也就是说,如果您必须使用bash
循环(也可以在 中使用zsh
):
while IFS= read -rd '' -u3 file; do
something with "$file"
done 3< <(find . -type f -print0 2> /dev/null)
Run Code Online (Sandbox Code Playgroud)
(进程替换,,,,,-r
所有从ksh复制的都是在2.05b之前或在与2.05b相同的版本中引入的-u
,所以应该在macos中可用)-d
<<<
/bin/bash
由于 macos 已经预装了 zsh,你也可以切换到 zsh,然后编写:
for file (**/*(ND.)) something with $file
Run Code Online (Sandbox Code Playgroud)
也可以看看: