Unix 中的 For 循环:包括子目录中的文件

Unix 中的 For 循环:包括子目录中的文件

Unix 中一个简单的 for 循环是:

for FILE in $BASE_WORK_DIR/*.pdf
   do
     echo $FILE
   done

这将回显.pdfBASE_WORK_DIR 目录中的所有文件。

BASE_WORK_DIR如果还包含子目录,其中也包含 pdf 文件怎么办?

在这种情况下,我如何设计我的 for 循环来获取所有 pdf 文件BASE_WORK_DIR及其子目录BASE_WORK_DIR

答案1

标准、规范且可靠的语法是:

find . -type f -name '*.pdf' -exec sh -c '
  for f do
    something with "$f"
  done' sh {} +

sh(请注意,如果文件列表很大,它可能会运行多次调用)。

对于zsh,等价于

for f (./**/*(.NDoN)) {
  something with "$f"
}

.对于-type fD包括隐藏文件,oN不费心对列表进行排序,N如果没有匹配的文件则不抱怨),但您不会收到有关您无权访问的目录的错误消息。

答案2

在 中bash4,并且需要遵循目录的符号链接,您可以启用globstar和使用**

shopt -s globstar
for file in "$base_work_dir"/**/*.pdf
do
  echo "$file"
done

否则在sh脚本中,find可能是最好的方法:

IFS='
'
set -f
for file in $(find "$base_work_dir" -name *.pdf)
do
  echo "$file"
done

(添加-L选项以find跟随符号链接,如bashglobstar)

请注意,如果任何文件名包含换行符,则会出现问题。

答案3

另一个解决方案find可以解决文件名中的换行符问题:

find "$BASE_WORK_DIR" -name '*.pdf' -print0 |
  while IFS= read -d '' -r file;do
    # your magic here
  done

买者自负:这只适用于 Zsh 和 Bash。

-print0find仅适用于GNU 等少数实现find-exec printf '%s\0' {} +如果您的发现不支持它,请使用它。

相关内容