如何获取目录中的目录列表,如 list.files() ,而不是“ list.dirs()”

对于某些人来说,这可能是一个非常简单的问题——我能够使用 list.files()获得给定目录中的文件列表,但是如果我想获得目录列表,我该如何做呢?它是不是就在我面前,作为 list.files()的一个选项?

另外,我使用的是 Windows,所以如果解决方案是使用 Linux/unix 命令,那对我不起作用。

例如,.NET 具有一个 Directory.GetFiles()方法和一个单独的 Directory.GetDirectories() 方法,所以我认为 R 应该有一个类似的对。

82175 次浏览

Update: A list.dirs function was added to the base package in revision 54353, which was included in the R-2.13.0 release in April, 2011.

list.dirs(path = ".", full.names = TRUE, recursive = TRUE)

So my function below was only useful for a few months. :)


I couldn't find a base R function to do this, but it would be pretty easy to write your own using:

dir()[file.info(dir())$isdir]

Update: here's a function (now corrected for Timothy Jones' comment):

list.dirs <- function(path=".", pattern=NULL, all.dirs=FALSE,
full.names=FALSE, ignore.case=FALSE) {
# use full.names=TRUE to pass to file.info
all <- list.files(path, pattern, all.dirs,
full.names=TRUE, recursive=FALSE, ignore.case)
dirs <- all[file.info(all)$isdir]
# determine whether to return full names or just dir names
if(isTRUE(full.names))
return(dirs)
else
return(basename(dirs))
}
list.dirs <- function(...) {
x <- dir(...)
x[file_test("-d", x)]
}

might be of use?

How might we do this recursively? (the recursive argument of dir breaks these functions because it never returns directory names, just the files within each directory, etc...).

You mention that you don't want to shell out to a Linux/UNIX command but I assume its ok to shell out to a Windows command. In that case this would do it:

shell("dir/ad/b", intern = TRUE)

and this would do it recursively:

shell("dir/ad/b/s", intern = TRUE)

Normally I would prefer the platform independent solutions of others here but particularly for interactive use where you are just concerned with getting the answer as simply and directly as possible this may be less work.

Just to update this thread:

I see that in the newer version of R (currently I'm using 2.5.1), there is now a list.dirs function included in the base install:

list.dirs implicitly has all.files = TRUE, and if recursive = TRUE, the answer includes path itself (provided it is a readable directory).

I had this problem a while back and used this recursive code to find all directories. Perhaps this can be of use?

list.dirs <- function(parent=".")   # recursively find directories
{
if (length(parent)>1)           # work on first and then rest
return(c(list.dirs(parent[1]), list.dirs(parent[-1])))
else {                          # length(parent) == 1
if (!is.dir(parent))
return(NULL)            # not a directory, don't return anything
child <- list.files(parent, full=TRUE)
if (!any(is.dir(child)))
return(parent)          # no directories below, return parent
else
return(list.dirs(child))    # recurse
}
}


is.dir <- function(x)    # helper function
{
ret <- file.info(x)$isdir
ret[is.na(ret)] <- FALSE
ret
}

What about something like this, give it a try:

dir('.')[file.info(dir('.',full.names=T))$isdir]

base R now includes a list.dirs function, so home-brewed variants are no longer necessary.

For example:

list.dirs('.', recursive=FALSE)