Bash - 迭代通过变量提供的文件列表

时间:2015-09-18 10:56:26

标签: bash

我的bash脚本中有以下内容:

local output_files=$(find "$output_folder" -type f)

for f in "$output_files"
do
  #do stuff
done

find命令返回多个文件时,上述操作无效,因为在for循环中评估\n$output_files似乎被剥离了,这意味着我们只得到for循环的一次迭代,因为所有文件名都连接成一个。

我做错了什么?

3 个答案:

答案 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