【发布时间】:2019-01-10 06:00:17
【问题描述】:
我知道如何遍历目录中的所有文件,例如:
for i in *
do
<some command>
done
但我想浏览目录中的所有文件,包括(尤其是!)子目录中的所有文件。有没有一种简单的方法可以做到这一点?
【问题讨论】:
标签: bash
我知道如何遍历目录中的所有文件,例如:
for i in *
do
<some command>
done
但我想浏览目录中的所有文件,包括(尤其是!)子目录中的所有文件。有没有一种简单的方法可以做到这一点?
【问题讨论】:
标签: bash
find 命令对于这类事情非常有用,前提是文件名中没有空格或其他特殊字符:
例如:
for i in $(find . -type f -print)
do
stuff
done
该命令从搜索开始(第一个参数)生成相对路径名。
正如所指出的,如果您的文件名包含空格或其他字符,这将失败。
您也可以使用-exec 选项来避免文件名中的空格问题。它为找到的每个文件执行给定的命令。大括号是文件名的占位符:
find . -type f -exec command {} \;
【讨论】:
find 是对的,但是对于包含空格、换行符或 shell 元字符的文件名,像这样迭代其输出会失败。
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
-exec 选项,效果很好。但它有一些缺点,比如你必须记住用 \; 终止命令,但是 xargs 在安全地并行运行任务以及检测任何命令失败的方式中也很有用。
find . -type f | while read line; do echo $line # Or some other command for each file encountered; done。这样做有什么我遗漏的/潜在的陷阱吗?
while read 循环存在问题。最糟糕的是,它不适用于包含空格或引号的文件名。所有-print0 的东西可能看起来没有必要,但多年来我经常被遗漏它所困扰。你会认为我现在已经学会了 :-) 另外,如果你可以在没有-L1 的情况下使用xargs,一切都会运行得更快。
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
【讨论】:
find 的这种合理的重新实现。见stackoverflow.com/questions/10067266/…