检查目录是否存在,如果不存在则创建

Cha*_*ase 361 r

我经常发现自己编写的R脚本会产生大量的输出.我发现把这个输出放到它自己的目录中更干净.我在下面写的内容将检查目录是否存在并移入其中,或创建目录然后移入其中.有没有更好的方法来解决这个问题?

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))

}
Run Code Online (Sandbox Code Playgroud)

rob*_*rit 382

用途showWarnings = FALSE:

dir.create(file.path(mainDir, subDir), showWarnings = FALSE)
setwd(file.path(mainDir, subDir))
Run Code Online (Sandbox Code Playgroud)

dir.create()如果目录已经存在,则不会崩溃,它只会打印出警告.因此,如果你能看到警告,那么这样做是没有问题的:

dir.create(file.path(mainDir, subDir))
setwd(file.path(mainDir, subDir))
Run Code Online (Sandbox Code Playgroud)

  • 使用`showWarnings = FALSE`时要注意,这也会隐藏其他警告,例如目录不可创建. (55认同)
  • @PraveenKesani这就是你要找的东西:`dir.create("test1/test2/test3 /",recursive = TRUE)`? (10认同)
  • ^有没有办法只抑制一个特定的警告? (5认同)
  • @Bas反应真的很晚,但是`suppressWarnings(<statement>)`会抑制那个声明的警告. (5认同)
  • 嗨,我想要创建嵌套目录,就像我在文件夹test1然后在它里面的test2里面test3 ...但是现在我面临着问题.是否有一种方法可以创建3级目录,即使directory1不退出? (2认同)

Mol*_*olx 154

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

ifelse(!dir.exists(file.path(mainDir, subDir)), dir.create(file.path(mainDir, subDir)), FALSE)
Run Code Online (Sandbox Code Playgroud)

FALSE如果目录已存在或不可创建,并且如果该目录TRUE不存在但已成功创建,则将返回此选项.

请注意,只需检查目录是否存在即可使用

dir.exists(file.path(mainDir, subDir))
Run Code Online (Sandbox Code Playgroud)

  • 只是要注意使用`ifelse()`进行非向量化分支是不好的做法. (9认同)
  • 使用if和else;) (5认同)
  • 那么,如果我们应该避免使用"ifelse",最好的做法是什么? (4认同)
  • @Bas因为您的代码错误地读取,好像正在发生某些矢量化.这就像使用矢量化的`|`而不是标量`||`.它有效,但是做法不好. (2认同)
  • 哦该死,所以我也通过使用“|”来错误地执行if语句,向量化是它有时不能与“||”一起使用的原因吗?我知道这不是主题,但我太想知道了。我一定会去阅读更多有关矢量化的内容。谢谢 (2认同)

zel*_*nix 17

就通用架构而言,我建议在目录创建方面采用以下结构.这将涵盖大多数潜在问题,并且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
}
Run Code Online (Sandbox Code Playgroud)

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

  • 你有什么理由使用 paste( ... ) vs file.path(mainDir, subDir) 。此外,如果你做了一个 path&lt;- file.path(mainDir, subDir) 你可以重复使用它 5 次使 if 语句更具可读性。 (6认同)

小智 17

单线:

if (!dir.exists(output_dir)) {dir.create(output_dir)}

例子:

dateDIR <- as.character(Sys.Date())
outputDIR <- file.path(outD, dateDIR)
if (!dir.exists(outputDIR)) {dir.create(outputDIR)}
Run Code Online (Sandbox Code Playgroud)


Sur*_*rya 10

这是简单的检查,如果不存在则创建目录:

## Provide the dir name(i.e 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!")
}
Run Code Online (Sandbox Code Playgroud)


小智 9

使用file.exists()来测试目录的存在是原始帖子中的一个问题.如果subDir包含现有文件的名称(而不仅仅是路径),则file.exists()将返回TRUE,但是对setwd()的调用将失败,因为您无法将工作目录设置为指向文件.

我建议使用file_test(op =" - d",subDir),如果subDir是现有目录,则返回"TRUE",但如果subDir是现有文件或不存在的文件或目录,则返回FALSE.同样,检查文件可以使用op =" - f"来完成.

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

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

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

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))
  }
}
Run Code Online (Sandbox Code Playgroud)

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

mainDir = getOption(someUniqueTag.mainDir)
subDir = getOption(someUniqueTag.subDir)
filename = "fileToBeCreated.txt"
file.create(file.path(mainDir, subDir, filename))
Run Code Online (Sandbox Code Playgroud)

此解决方案使工作目录处于用户的控制之下.


Amy*_*y M 8

我知道这个问题不久前就被问过,但如果有用的话,该here包对于不必引用特定文件路径并使代码更加可移植确实很有帮助。它会自动将您的工作目录定义为.Rproj文件所在的目录,因此以下内容通常就足够了,而无需定义工作目录的文件路径:

library(here)

if (!dir.exists(here(outputDir))) {dir.create(here(outputDir))}

Run Code Online (Sandbox Code Playgroud)


use*_*678 6

我遇到了R 2.15.3的问题,在尝试在共享网络驱动器上递归创建树结构时,我会收到权限错误.

为了解决这个奇怪的问题,我手动创建结构;

mkdirs <- function(fp) {
    if(!file.exists(fp)) {
        mkdirs(dirname(fp))
        dir.create(fp)
    }
} 

mkdirs("H:/foo/bar")
Run Code Online (Sandbox Code Playgroud)