我知道如何遍历一个目录中的所有文件,例如:
for i in *
do
<some command>
done
但是我想遍历目录中的所有文件,包括(尤其是!)子目录中的所有文件。有没有简单的方法可以做到这一点?
我知道如何遍历一个目录中的所有文件,例如:
for i in *
do
<some command>
done
但是我想遍历目录中的所有文件,包括(尤其是!)子目录中的所有文件。有没有简单的方法可以做到这一点?
find
命令非常有用,特别是当文件名中没有空格或其他特殊字符时:
例如:
for i in $(find . -type f -print)
do
stuff
done
该命令从搜索的起点(第一个参数)生成相对路径名。
正如指出的那样,如果您的文件名包含空格或某些其他字符,则会失败。
您也可以使用-exec
选项来避免文件名中的空格问题。它会为找到的每个文件执行给定的命令。大括号是文件名的占位符:
find . -type f -exec command {} \;
find
和xargs
是用于递归处理目录及其子目录内容的强大工具。例如:
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
-I
标志,它意味着-L1
并允许参数位置,就像这个例子:seq 10 | xargs -Iarg echo arg --more
。 - alexgirao-exec
选项,这个选项工作得非常好。但它也有一些怪癖,例如你必须记住在命令结尾加上\;
,但是正如所示,xargs 也是一个很有用的工具,可以安全地并行运行任务,并检测任何命令是否失败。 - Gem Taylorfind . -type f | while read line; do echo $line # Or some other command for each file encountered; done
。我是否遗漏了什么或者存在潜在的问题? - Sebastianwhile read
循环存在问题。最糟糕的是,它无法处理文件名中带有空格或引号等特殊字符的情况。所有 -print0
的东西可能看起来都是不必要的,但多年来我经常因为没有加上它而受到影响。你会认为我现在应该已经学习到了 :-) 另外,如果你可以在不使用 -L1
的情况下使用 xargs
,那么一切都会运行得更快。 - Jonrecurse() {
path=$1
If [ -d "$path" ] ; then
for i in "$path/"*
do
recurse "$i"
done
elif [ -f "$path" ] ; then
do-something
fi
}
调用recurse
并将第一个位置参数作为您想要开始的目录路径传递。
例如:recurse /path
find
命令是正确的,但像这样迭代其输出会因文件名包含空格、换行符或 shell 特殊字符而失败。 - chepner