有没有更快的方法把目录中的所有文件列出来?
我有下面这个文件夹
parent_folder <- "C:/Users/Name/Documents/Folder"
对于该文件夹中的所有文件(也就是说里面有子文件夹、子子文件夹、子子子文件夹等),我想做一个汇总,获取扩展名、大小等信息。
我正在使用当前的代码:
files <- list.files(path = parent_folder, recursive = TRUE, full.names = TRUE)
info <- file.info(files)
df_files <- data.frame(
file_name = basename(files),
date_created = info$ctime,
size = info$size,
extension = tools::file_ext(files),
parent_folder = dirname(files),
full_path = files,
stringsAsFactors = FALSE
)
head(df_files)
代码中的 'info' 对象运行得非常慢。
有什么办法可以加快吗?例如,是否应该并行处理(也就是说把每个子文件夹分配给一个处理核心)?还有什么可以做来改进吗?
解决方案
在类Unix系统上,我们可能使用 system() 来调用 find。
fs_index_sys <- \(wd, recursive=FALSE) {
depth <- if (recursive) "" else "-maxdepth 1"
cmd <- sprintf(
"find %s %s -printf '%%f\\t%%T@\\t%%s\\t%%p\\n'",
shQuote(wd), depth
)
x <- system(cmd, intern=TRUE)
df <- read.delim(
text=x, sep='\t', header=FALSE, quote="",
col.names=c("file_name", "mtime", "size", "full_path"),
colClasses=c("character", "numeric", "numeric", "character")
)
df$date_created <- as.POSIXct(df$mtime, origin="1970-01-01")
df$mtime <- NULL
df$parent_folder <- dirname(df$full_path)
df$extension <- sub("^.*\\.", "", df$file_name)
df$extension[!grepl("\\.", df$file_name)] <- ""
df
}
我将 recursive=FALSE 设为默认值,对所有子目录设置 TRUE。列可以按需要扩展。
结果
fs_index_sys('/home/jay/Downloads', TRUE) |> head()
# file_name size full_path date_created parent_folder extension
# 1 DIR_001 94208 /home/user/DIR_001 2026-03-12 08:48:47 /home/user
# 2 FILE_001 4036 /home/user/DIR_001/FILE_001.flatpak 2025-01-22 16:45:04 /home/user/DIR_001 flatpakref
# 3 FILE_002 20245712 /home/user/DIR_001/FILE_002 2024-09-27 13:09:34 /home/user/DIR_001
# 4 FILE_003 4016 /home/user/DIR_001/FILE_003.flatpak 2025-01-22 17:08:42 /home/user/DIR_001 flatpakref
# 5 FILE_004 12974 /home/user/DIR_001/FILE_004.xlsx 2024-12-30 23:04:12 /home/user/DIR_001 xlsx
# 6 FILE_005 4034 /home/user/DIR_001/FILE_005.flatpak 2025-01-22 18:56:05 /home/user/DIR_001 flatpakref
基准测试
fs_index_R <- \(wd) {
files <- list.files(path=wd, recursive=TRUE, full.names=TRUE)
info <- file.info(files)
data.frame(
file_name=basename(files),
date_created=info$ctime,
size=info$size,
extension=tools::file_ext(files),
parent_folder=dirname(files),
full_path=files,
stringsAsFactors=FALSE
)
}
fs_index_fs <- \(wd) {
fs::dir_info(wd, recurse=TRUE, fail=FALSE)
}
wd <- '/home/jay/Downloads'
> microbenchmark::microbenchmark(
+ fs_index_R(wd),
+ fs_index_sys(wd, TRUE),
+ fs_index_fs(wd),
+ times=3L
+ )
Unit: milliseconds
expr min lq mean median uq max neval cld
fs_index_R(wd) 29.88719 30.59268 31.40457 31.29817 32.16325 33.02834 3 a
fs_index_sys(wd) 18.55746 20.32725 21.37669 22.09705 22.78630 23.47555 3 a
fs_index_fs(wd) 2222.97897 2712.30972 2882.19211 3201.64046 3211.79868 3221.95689 3 b
fs_index_sys() 相比于OP的基础R 方法大约快了30%。不确定为什么所宣传的 fs::dir_info() 在我的系统上运行得这么慢。
其中 fs_index_sys() 似乎更完整/更全面:
> fs_index_R(wd) |> dim()
[1] 4756 6
> fs_index_sys(wd, TRUE) |> dim()
[1] 4784 6
> fs_index_fs(wd) |> dim()
[1] 4775 18
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。