使用Bash循环遍历目录及其子目录中的所有文件

10

我知道如何遍历一个目录中的所有文件,例如:

for i in *
do
  <some command>
done

但是我想遍历目录中的所有文件,包括(尤其是!)子目录中的所有文件。有没有简单的方法可以做到这一点?

3个回答

14
< p > find 命令非常有用,特别是当文件名中没有空格或其他特殊字符时:

例如:

for i in $(find . -type f -print)
do
    stuff
done

该命令从搜索的起点(第一个参数)生成相对路径名。

正如指出的那样,如果您的文件名包含空格或某些其他字符,则会失败。

您也可以使用-exec选项来避免文件名中的空格问题。它会为找到的每个文件执行给定的命令。大括号是文件名的占位符:

find . -type f -exec command {} \;

7
find 命令是正确的,但像这样迭代其输出会因文件名包含空格、换行符或 shell 特殊字符而失败。 - chepner

6

findxargs是用于递归处理目录及其子目录内容的强大工具。例如:

find . -type f -print0 | xargs -0 command

该命令将在当前目录及其子目录中的文件批次上运行command-print0-0参数避免了包含空格、引号或其他元字符的文件名通常会出现的问题。

如果command只需要一个参数,您可以使用-L1限制传递给它的文件数量。

find . -type f -print0 | xargs -0 -L1 command

正如alexgirao建议的那样,xargs还可以使用-I给参数命名,如果command需要选项,则这会提供一些灵活性。 -I意味着-L1

find . -type f -print0 | xargs -0 -Iarg command arg --option

1
不错的回答,也许你还应该举例说明使用-I标志,它意味着-L1并允许参数位置,就像这个例子:seq 10 | xargs -Iarg echo arg --more - alexgirao
find 命令还有其自带的 -exec 选项,这个选项工作得非常好。但它也有一些怪癖,例如你必须记住在命令结尾加上\;,但是正如所示,xargs 也是一个很有用的工具,可以安全地并行运行任务,并检测任何命令是否失败。 - Gem Taylor
我对这个答案有点困惑。虽然有帮助,但似乎涉及了一些不必要的步骤/部分。我已经编写了这段代码片段(使用此答案和其他答案),它似乎可以实现我想要的功能:find . -type f | while read line; do echo $line # Or some other command for each file encountered; done。我是否遗漏了什么或者存在潜在的问题? - Sebastian
@Sebastian 是的,确实使用 while read 循环存在问题。最糟糕的是,它无法处理文件名中带有空格或引号等特殊字符的情况。所有 -print0 的东西可能看起来都是不必要的,但多年来我经常因为没有加上它而受到影响。你会认为我现在应该已经学习到了 :-) 另外,如果你可以在不使用 -L1 的情况下使用 xargs,那么一切都会运行得更快。 - Jon

0
recurse() {
  path=$1
  If [ -d "$path" ] ; then
     for i in "$path/"*
     do
        recurse "$i"
     done
  elif [ -f "$path" ] ; then
     do-something
  fi
}

调用recurse并将第一个位置参数作为您想要开始的目录路径传递。

例如:recurse /path


缺乏引用会彻底破坏这个本来合理的“查找”重新实现。请参见https://dev59.com/NWkw5IYBdhLWcg3wMHum - tripleee
哦,还少了一个美元符号。 - tripleee

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接