Проверьте существование каталога и создайте, если не существует - PullRequest
343 голосов
/ 18 ноября 2010

Я часто пишу сценарии на 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))

}

Ответы [ 7 ]

362 голосов
/ 18 ноября 2010

Использование 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))
144 голосов
/ 22 апреля 2015

По состоянию на 16 апреля 2015 года, с выпуском 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))
17 голосов
/ 20 января 2014

С точки зрения общей архитектуры, я бы порекомендовал следующую структуру для создания каталогов.Это покроет большинство потенциальных проблем, и любые другие проблемы с созданием каталога будут обнаружены вызовом 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.

9 голосов
/ 02 сентября 2017

Вот простая проверка , и создает каталог, если его не существует:

## 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!")
}
8 голосов
/ 13 сентября 2015

Использование file.exists () для проверки существования каталога является проблемой в оригинальном посте. Если subDir включает имя существующего файла (а не просто путь), file.exists () вернет TRUE, но вызов setwd () завершится неудачно, потому что вы не можете установить рабочий каталог так, чтобы он указывал на файл.

Я бы рекомендовал использовать file_test (op = "- d", subDir), который будет возвращать "TRUE", если subDir является существующим каталогом, и FALSE, если subDir является существующим файлом или несуществующим файлом или каталогом. , Аналогично, проверка файла может быть выполнена с помощью 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))

Это решение оставляет рабочий каталог под контролем пользователя.

6 голосов
/ 28 сентября 2015

У меня была проблема с R 2.15.3, из-за которой при попытке рекурсивного создания древовидной структуры на общем сетевом диске я получил ошибку разрешения.

Чтобы обойти эту странность, я вручную создаю структуру;

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

mkdirs("H:/foo/bar")
2 голосов
/ 05 июля 2014

Чтобы выяснить, является ли путь допустимым каталогом, попробуйте:

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

file.info не заботится о косой черте в конце.

file.exists в 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"]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...