我经常发现自己在编写生成大量输出的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))
    
}

当前回答

在最初的文章中,使用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和file . 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))

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

其他回答

在最初的文章中,使用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和file . 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))

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

下面是简单的检查,如果不存在就创建dir:

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

要找出一个路径是否是一个有效的目录,请尝试:

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

File.info不关心结尾的斜杠。

文件。在Windows上存在的目录如果以斜杠结尾将失败,如果没有斜杠则成功。因此,这不能用于确定路径是否为目录。

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

Package hutils(由我编写)具有函数provider .dir(path)和provider .file(path)来检查路径上的目录/文件是否存在,如果它们不存在则创建它们。

我在R 2.15.3中遇到了一个问题,当我试图在共享网络驱动器上递归地创建一个树结构时,我会得到一个权限错误。

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

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

mkdirs("H:/foo/bar")