检查目录的存在和创build如果不存在

我经常发现自己编写了可以产生大量输出的R脚本。 我觉得把这个输出放到它自己的目录里是比较简单的。 我在下面写的将检查一个目录的存在,并进入它,或创build目录,然后进入它。 有没有更好的方法来解决这个问题?

mainDir <- "c:/path/to/main/dir" subDir <- "outputDirectory" if (file.exists(subDir)){ setwd(file.path(mainDir, subDir)) } else { dir.create(file.path(mainDir, subDir)) setwd(file.path(mainDir, subDir)) } 

使用showWarnings = FALSE

 dir.create(file.path(mainDir, subDir), showWarnings = FALSE) setwd(file.path(mainDir, subDir)) 

如果目录已经存在, dir.create()不会崩溃,它只会打印出警告。 所以如果你能忍受看到警告,这样做没有问题:

 dir.create(file.path(mainDir, subDir)) setwd(file.path(mainDir, subDir)) 

截至2015年4月16日,随着R 3.2.0的发布,有一个名为dir.exists()的新函数。 要使用此函数并创build该目录(如果该目录不存在),可以使用:

 ifelse(!dir.exists(file.path(mainDir, subDir)), dir.create(file.path(mainDir, subDir)), FALSE) 

如果该目录已经存在或者不可用,这将返回FALSE ,如果它不存在但是被成功创build,则返回TRUE

请注意,只要检查目录是否存在,您可以使用

 dir.exists(file.path(mainDir, subDir)) 

就通用体系结构而言,我会build议关于目录创build的以下结构。 这将覆盖大多数潜在的问题,目录创build的任何其他问题将由dir.create调用检测到。

 mainDir <- "~" subDir <- "outputDirectory" if (file.exists(paste(mainDir, subDir, "/", sep = "/", collapse = "/"))) { cat("subDir exists in mainDir and is a directory") } else if (file.exists(paste(mainDir, subDir, sep = "/", collapse = "/"))) { cat("subDir exists in mainDir but is a file") # you will probably want to handle this separately } else { cat("subDir does not exist in mainDir - creating") dir.create(file.path(mainDir, subDir)) } if (file.exists(paste(mainDir, subDir, "/", sep = "/", collapse = "/"))) { # By this point, the directory either existed or has been successfully created setwd(file.path(mainDir, subDir)) } else { cat("subDir does not exist") # Handle this error as appropriate } 

另外请注意,如果~/foo不存在,除非指定recursive = TRUE否则调用dir.create('~/foo/bar')将失败。

使用file.exists()来testing目录是否存在是原始文章中的一个问题。 如果subDir包含现有文件的名称(而不仅仅是一个path),则file.exists()将返回TRUE,但是对setwd()的调用会失败,因为您不能将工作目录设置为指向文件。

我build议使用file_test(op =“ – d”,subDir),如果subDir是现有目录,将返回“TRUE”;如果subDir是现有文件或不存在的文件或目录,则返回FALSE。 同样,检查一个文件可以用op =“ – f”来完成。

另外,如另一条评论所述,工作目录是R环境的一部分,应该由用户来控制,而不是脚本。 理想情况下,脚本不应该改变R环境。 为了解决这个问题,我可能使用options()来存储一个全局可用的目录,我想要所有的输出。

因此,请考虑以下解决scheme,其中someUniqueTag只是程序员定义的选项名称前缀,这使得不太可能存在具有相同名称的选项。 (例如,如果您正在开发名为“filer”的软件包,则可以使用filer.mainDir和filer.subDir)。

以下代码将用于设置稍后可用于其他脚本的选项(从而避免在脚本中使用setwd()),并在必要时创build该文件夹:

 mainDir = "c:/path/to/main/dir" subDir = "outputDirectory" options(someUniqueTag.mainDir = mainDir) options(someUniqueTag.subDir = "subDir") if (!file_test("-d", file.path(mainDir, subDir)){ if(file_test("-f", file.path(mainDir, subDir)) { stop("Path can't be created because a file with that name already exists.") } else { dir.create(file.path(mainDir, subDir)) } } 

然后,在任何需要在subDir中操作文件的后续脚本中,可以使用如下所示的内容:

 mainDir = getOption(someUniqueTag.mainDir) subDir = getOption(someUniqueTag.subDir) filename = "fileToBeCreated.txt" file.create(file.path(mainDir, subDir, filename)) 

该解决scheme在用户的控制下离开工作目录。

我在R 2.15.3中遇到了一个问题,在试图在共享networking驱动器上recursion地创build一个树结构的时候,我会得到一个权限错误。

为了解决这个问题,我手动创build结构;

 mkdirs <- function(fp) { if(!file.exists(fp)) { mkdirs(dirname(fp)) dir.create(fp) } } mkdirs("H:/foo/bar") 

要找出path是否是有效的目录,请尝试:

 file.info(cacheDir)[1,"isdir"] 

file.info不关心最后的斜线。

如果以斜线结尾,则Windows上的file.exists将会失败,并且在没有它的情况下成功。 所以这不能用来确定一个path是否是一个目录。

 file.exists("R:/data/CCAM/CCAMC160b_echam5_A2-ct-uf.-5t05N.190to240E_level1000/cache/") [1] FALSE file.exists("R:/data/CCAM/CCAMC160b_echam5_A2-ct-uf.-5t05N.190to240E_level1000/cache") [1] TRUE file.info(cacheDir)["isdir"] 

这是简单的检查并创build目录如果不存在:

 ## Provide the dir name(ie sub dir) that you want to create under main dir: output_dir <- file.path(main_dir, sub_dir) if (!dir.exists(output_dir)){ dir.create(output_dir) } else { print("Dir already exists!") }