使用 r 进行文件夹管理:检查目录是否存在,如果不存在则创建它

问题描述 投票:0回答:11

我经常发现自己编写的 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))
    
}
r directory path filesystems
11个回答
511
投票

使用

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

201
投票

自 2015 年 4 月 16 日起,随着

R 3.2.0
的发布,出现了一个名为
dir.exists()
的新功能。要使用此功能并创建目录(如果不存在),可以使用:

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

如果目录已存在或无法创建,则返回

FALSE
;如果目录不存在但已成功创建,则返回
TRUE

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

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

41
投票

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

## 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!")
}

40
投票

单行:

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

19
投票

就一般架构而言,我会推荐以下关于目录创建的结构。这将涵盖大多数潜在问题,并且目录创建的任何其他问题都将通过

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
不存在,则对
dir.create('~/foo/bar')
的调用将会失败,除非您指定
recursive = TRUE


13
投票

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

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

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

mkdirs("H:/foo/bar")

11
投票

使用 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))
  }
}

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

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

此解决方案将工作目录置于用户的控制之下。


8
投票

我知道这个问题不久前就被问过,但如果有用的话,

here
包对于不必引用特定文件路径并使代码更可移植确实很有帮助。它会自动将您的工作目录定义为您的
.Rproj
文件所在的目录,因此以下内容通常就足够了,而无需定义工作目录的文件路径:

library(here)

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


4
投票

hutils
(我编写的)具有功能
provide.dir(path)
provide.file(path)
来检查
path
处的目录/文件是否存在,如果不存在则创建它们。


3
投票

要查明路径是否是有效目录,请尝试:

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

file.info
不关心末尾的斜杠。

在 Windows 上,如果目录以斜杠结尾,

file.exists
将会失败,而如果没有斜杠则成功。所以这不能用来确定路径是否是目录。

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"]

0
投票

我偶然发现了另一种方式,我认为这不是最好的,但很有趣。

path <- "your/path"
dir.exists(path) || dir.create(path)
最新问题
© www.soinside.com 2019 - 2024. All rights reserved.