递归列出目录中所有文件的最快方法

递归列出目录中所有文件的最快方法

我正在尝试获取目录中所有文件的相对路径。它可以运行数十万个文件,所以我需要它速度快。

我已经尝试过find .并且rg --filesrg存在ripgrep)并且rg速度大约快 6 倍。

有没有一种本地方法可以更好甚至更快地完成此操作?

答案1

这会作弊并假设您有更新的位置数据库(例如定位),但它应该是最快的,因为您正在解析目录内容的缓存。

locate "$PWD/*" |awk -v len="${#PWD}" '{ print substr($0, len+2) }'

数据库locate每天都会更新,因此您可能必须sudo updatedb提前运行,这显然需要一段时间,因为它正在索引整个文件系统(并且可能不如 ripgrep 那么快),但如果您需要执行几次,则缓存一次就可以了仍然是要走的路。

awk代码打印相对于给定路径的命中。您可以将其设为这样的函数:

# Usage: indir [DIRECTORY]
# Show recursive contents of DIRECTORY (defaults to current directory)
indir() {
  d="$(readlink -f "${1:-$PWD}")"
  locate "$d/*" |awk -v len="${#d}" '{ print substr($0, len+2) }'
}

readlink -f(来自 GNU Coreutils)将规范化您的输入,因此您可以运行indir .orindir ../foo并且它仍然可以工作(尽管输出将相对于 DIRECTORY,因此它将显示../foo/bar/bazbar/baz)。

正如此答案的评论中所述,如果查询路径名中存在通配字符(?*或) ,您将遇到问题。[…]您可以通过使用反斜杠转义它们来解决这个问题(尽管请注意这会改变长度)。

或者,如果 GNU grep 是使用 libpcre 支持编译的,则可以使用 GNU grep 来执行此操作:

# Usage: indir [DIRECTORY]
# Show recursive contents of DIRECTORY (defaults to current directory)
indir() {
  d="$(readlink -f "${1:-$PWD}")"
  locate "$d/*" |grep -Po "^\Q$d/\E\K.+"
}

这将使用 PCRE 运行 grep 并仅打印匹配的内容。正则表达式有点复杂(另请参阅正则表达式101解释)。它仅在行的开头匹配 ( ^),然后成为文字字符串匹配(禁止和\Q…\E之间的正则表达式解释),然后表示应报告为匹配的内容的开头。最终匹配该路径之后的所有内容,这是 grep 报告的唯一内容。我在 中放入了一个文字,以确保我们不匹配目录名称本身,尽管这也确保我们不匹配不同的路径,例如匹配.\Q\E\K.+/\Q…\E/path/to/dirt/path/to/dir

相关内容