Проверить наличие директории и создать, если не существует
Я часто нахожу, что пишу сценарии 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))
}
Ответы
Ответ 1
Используйте 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))
Ответ 2
По состоянию на 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))
Ответ 3
Что касается общей архитектуры, я бы рекомендовал следующую структуру в отношении создания каталога. Это затронет большинство потенциальных проблем, и любые другие проблемы с созданием каталогов будут обнаружены вызовом 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
.
Ответ 4
Здесь простая проверка, и создает каталог, если он не существует:
## 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!")
}
Ответ 5
Использование файла file.exists() для проверки наличия каталога является проблемой в исходном сообщении. Если в subDir было указано имя существующего файла (а не только путь), file.exists() вернет TRUE, но вызов setwd() завершится неудачно, потому что вы не можете установить рабочий каталог в файл.
Я бы рекомендовал использовать file_test (op = "- d", subDir), который вернет "TRUE", если subDir - это существующий каталог, но FALSE, если subDir - это существующий файл или несуществующий файл или каталог, Аналогично, проверка файла может быть выполнена с помощью op = "- f".
Кроме того, как описано в другом комментарии, рабочий каталог является частью среды R и должен контролироваться пользователем, а не script. Сценарии должны, в идеале, не изменять среду R. Чтобы решить эту проблему, я мог бы использовать options() для хранения доступного в глобальном масштабе каталога, где мне нужен весь мой вывод.
Итак, рассмотрим следующее решение, где someUniqueTag - только определенный программистом префикс для имени опции, что делает маловероятным, что опция с тем же именем уже существует. (Например, если вы разрабатывали пакет под названием "filer", вы можете использовать filer.mainDir и filer.subDir).
Следующий код будет использоваться для установки параметров, доступных для использования позднее в других сценариях (таким образом, избегая использования setwd() в script) и при необходимости создайте папку:
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))
}
}
Затем в любом последующем script, который должен был обрабатывать файл в subDir, вы можете использовать что-то вроде:
mainDir = getOption(someUniqueTag.mainDir)
subDir = getOption(someUniqueTag.subDir)
filename = "fileToBeCreated.txt"
file.create(file.path(mainDir, subDir, filename))
Это решение оставляет рабочий каталог под контролем пользователя.
Ответ 6
У меня возникла проблема с R 2.15.3, когда при попытке создать рекурсивную структуру дерева на общем сетевом диске я получил бы ошибку разрешения.
Чтобы обойти эту странность, я вручную создаю структуру;
mkdirs <- function(fp) {
if(!file.exists(fp)) {
mkdirs(dirname(fp))
dir.create(fp)
}
}
mkdirs("H:/foo/bar")
Ответ 7
Чтобы выяснить, является ли путь действительным каталогом, попробуйте:
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"]
Ответ 8
Один лайнер:
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)}