我被某项任务困住了。我想要的是一个函数,给定一个目录路径,它将返回一个递归列表作为输出。
输出的形式应该是 myList$dir$subdir$subdir$fullFilePath
所以基本上我想将目录树表示为某个列表。我获取了所有文件,获取了每个文件的所有子目录,但我不知道如何将它们全部放入具有多个级别的列表中。
我被某项任务困住了。我想要的是一个函数,给定一个目录路径,它将返回一个递归列表作为输出。
输出的形式应该是 myList$dir$subdir$subdir$fullFilePath
所以基本上我想将目录树表示为某个列表。我获取了所有文件,获取了每个文件的所有子目录,但我不知道如何将它们全部放入具有多个级别的列表中。
这是使用递归的解决方案:
tree.list <- function(file.or.dir) {
isdir <- file.info(file.or.dir)$isdir
if (!isdir) {
out <- file.or.dir
} else {
files <- list.files(file.or.dir, full.names = TRUE,
include.dirs = TRUE)
out <- lapply(files, tree.list)
names(out) <- basename(files)
}
out
}
我在一个小目录上测试了它
test.dir <- tree.list("./test")
test.dir
# $a
# $a$`1.txt`
# [1] "./test/a/1.txt"
#
# $a$aa
# $a$aa$`2.txt`
# [1] "./test/a/aa/2.txt"
#
# $b
# $b$`3.txt`
# [1] "./test/b/3.txt"
如果这对您的需求来说太慢了,我会考虑将所有文件读入一次调用中list.files
,recursive = TRUE
然后进行一些解析。
这是一个丑陋的黑客。
mypath <- 'a/b/c/d'
makelist <- function(filepath, fsep = '/'){
unlisted <- unlist(strsplit(filepath, fsep))
nsubs <- length(unlisted)
mylistcall <- paste(paste(rep('list(', nsubs), unlisted, collapse = '='),
'= NULL', paste(rep(')', nsubs), collapse = ''))
mylist <- eval(parse(text = mylistcall))
return(mylist)
}
makelist(mypath)
$a
$a$b
$a$b$c
$a$b$c$d
NULL
记住
fortune(106)
If the answer is parse() you should usually rethink the question.
-- Thomas Lumley
R-help (February 2005)
然而,在这种情况下,我会说我应该重新考虑答案。
这是@flodel 使用该purrr
包的精彩解决方案的较短变体:
library( purrr )
tree_list <- function( file_or_dir ) {
f <- partial(list.files, full.names=TRUE, include.dirs=TRUE) %>%
compose(tree_list, .)
file_or_dir %>% set_names( basename(.) ) %>% map_if(dir.exists, f)
}
第一行定义了一个f
扩展其参数的函数,使用list.files( ..., full.names=TRUE, include.dirs=TRUE)
then 应用于tree_list()
扩展。
第二行将定义的函数应用于f
原始参数中的所有目录。