bash - 如何在非 Bash Shell 中迭代 Null 分隔结果

标签 bash shell

好的,所以我有一个脚本来处理 find 的空分隔输出,我可以像这样使用 bash shell 轻松处理它:

#!/bin/sh
find "$1" -print0 | while read -rd '' path; do echo "$path"; done

相当愚蠢的示例,因为它只是将结果转换为换行符,但这只是为了让您了解我想要做什么。这种基本方法效果很好,并且避免了由于各种文件系统上的文件可能包含换行符而导致的潜在问题。

但是,我需要在非 bash shell 上做同样的事情,这意味着我失去了对 read -d 的支持。那么,在不求助于 bash(或其他 shell)特定功能的情况下,有没有一种方法可以像上面那样处理以 null 分隔的结果?

如果不是,什么是最好的保护自己免受结果换行的方法?我在想我也许可以使用 find-exec 选项用某种转义值替换文件名中的换行符,但我不确定查找和替换新行的最佳方法(例如,我不能使用 tr)或使用什么替换,这就是为什么空字符是最好的选择(如果可用)。

最佳答案

参见 How can I find and safely handle file names containing newlines, spaces or both? .

例如,您可以使用 find -exec:

find [...] -exec <command> {} \;

xargs -0:

find [...] -print0 | xargs -r0 <command>

请注意,在上面的示例中,您仍然需要设置 IFS 否则您将删除前导/尾随空格:

while IFS= read -rd '' file; do
   do_something_with "${file}"
done

你是对的,这个read只能在bash中正常工作,这真是太可惜了。我通常不会在意文件名中可能的换行符,只是确保可移植代码在出现时不会中断(而不是忽略问题和脚本爆炸),我认为这足以满足大多数情况,例如

while IFS= read -r file; do
    [ -e "${file}" ] || continue # skip over truncated filenames due to newlines
    do_something_file "${file}"
done < <(find [...])

或使用 globbing(如果可能)其行为正确:

for file in *.foo; do
    [ -e "${file}" ] || continue # or use nullglob
    do_something_file "${file}"
done

关于bash - 如何在非 Bash Shell 中迭代 Null 分隔结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22762816/

相关文章:

bash - 列出带有出现次数的文本文件中的所有单词?

linux - 使用 SED/Perl 删除包含数字的字符串部分

linux - 在 Linux 中删除 10 天前的旧文件夹

在linux上挂载USB的java代码

linux - bash重定向到同一个文件的一致性

shell - Xcode 项目中重复目标的脚本

bash - 如何在 sh -c "..."命令中分配 shell 变量?

bash - 命令替换字符串中的复合命令

macos - 如何在 Mac OS 上通过 PID 获取进程用户名?

c - 迷你 shell 背景