好的,所以我有一个处理空分隔输出的脚本find,我可以使用像这样的bash shell轻松处理它:
#!/bin/sh
find "$1" -print0 | while read -rd '' path; do echo "$path"; done
Run Code Online (Sandbox Code Playgroud)
相当愚蠢的例子,因为它只是将结果转换为新行,但它只是让你知道我想要做什么.这种基本方法效果很好,并且避免了由于文件可能在各种文件系统上包含换行而导致的潜在问题.
但是,我需要在非bash shell上做同样的事情,这意味着我失去了支持read -d.因此,如果不采用bash(或其他shell)特定功能,有没有一种方法可以处理与上述类似的空分离结果?
如果没有,最好保护自己免受结果中的新线条影响?我以为我可以使用-exec选项find来替换文件名中的新行与某种转义值,但我不确定找到和替换新行的最佳方法(我不能tr用于示例)或使用什么替换,这就是为什么空字符是最好的选择(如果可用).
你可以使用find -exec:
find [...] -exec <command> {} \;
Run Code Online (Sandbox Code Playgroud)
或者xargs -0:
find [...] -print0 | xargs -r0 <command>
Run Code Online (Sandbox Code Playgroud)
请注意,在上面的示例中,您仍然需要设置IFS或者您将修剪前导/尾随空格:
while IFS= read -rd '' file; do
do_something_with "${file}"
done
Run Code Online (Sandbox Code Playgroud)
你是对的,这是一个真正的无赖,read这只适用于bash.我通常不会对文件名中可能的新行给出该死的,只是确保可移植代码在发生时不会中断(而不是忽略问题和脚本爆炸),我认为这对于大多数场景来说都是足够的,例如
while IFS= read -r file; do
[ -e "${file}" ] || continue # skip over truncated filenames due to newlines
do_something_file "${file}"
done < <(find [...])
Run Code Online (Sandbox Code Playgroud)
或使用globbing(如果可能)行为正确:
for file in *.foo; do
[ -e "${file}" ] || continue # or use nullglob
do_something_file "${file}"
done
Run Code Online (Sandbox Code Playgroud)
添加到@AdrianFrühwirth的优秀答案:
这是一个严格遵守POSIX的解决方案,包括shell代码和实用程序及其使用的选项:
find . -exec sh -c 'for f in "$@"; do echo "$f"; done' - {} +
Run Code Online (Sandbox Code Playgroud)
这避免了两个find的-print0和read -d.
(假设您的shell代码将被多次调用,即当有太多输入文件名不适合单个命令行时,有一个假设的机会.
getconf ARG_MAX告诉您平台调用外部实用程序的最大命令行长度,但请注意,在实践中限制较低;请参阅http://www.in-ulm.de/~mascheck/various/argmax/)
| 归档时间: |
|
| 查看次数: |
1765 次 |
| 最近记录: |