有没有更快的方法把目录中的所有文件列出来?

编程语言 2026-07-11

我有下面这个文件夹

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导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章