我的bash脚本中有以下内容:
local output_files=$(find "$output_folder" -type f)
for f in "$output_files"
do
#do stuff
done
当find
命令返回多个文件时,上述操作无效,因为在for循环中评估\n
时$output_files
似乎被剥离了,这意味着我们只得到for循环的一次迭代,因为所有文件名都连接成一个。
我做错了什么?
答案 0 :(得分:3)
根据#do stuff
的内容,您可以使用-exec
的{{1}}指令:示例使用简单命令find
:
cat
如果你想做一些更复杂的事情,唯一安全的方法是:
find "$output_folder" -type f -exec cat {} \;
请注意,这意味着您的find "$output_folder" -type f -print0 | while IFS= read -r -d '' f; do
#do stuff
done
版本支持find
谓词(并非所有版本都支持,但GNU -print0
支持)。另请注意,find
循环在子shell中运行,因此在循环之后将丢弃对变量的任何修改。如果这是一个问题,您可以使用while
(Bash≥4.2,感谢@chepner)或shopt -s lastpipe
命令的进程替换:
find
答案 1 :(得分:1)
如果您使用bash
4,则可以完全避免find
:
shopt -s globstar
for f in "$output_folder"/**/*; do
do
[[ -f $f && ! -h $f ]] || continue # -type f
# dostuff
done
如果您更关心跳过目录而不是严格匹配常规文件(也就是说,您没有考虑层次结构中套接字,命名管道等的可能性),则可以使用[[ ! -d $f ]]
代替。
(对于常规文件的符号链接,-f
测试会成功,而-type f
则不会。使用-h
*过滤符号链接以保持与-type f
的兼容性尽可能。)
这使您可以安全,干净地处理所有合法文件名。 (但是,如果您没有使用find
更难以在纯bash
模拟的其他原色,这通常只是一种选择。)
*或-L
,其行为与-h
相同。 POSIX规范没有提到为什么两者都存在;我怀疑这是为了向后兼容现有的实现。
答案 2 :(得分:0)
删除$outputfiles
循环中for
周围的引号。
for f in $output_files
do
#do stuff
done
正如@anubhava所提到的,你也可以使用command substitution
。
for f in $(find "$output_folder" -type f)
do
# do stuff
done