디렉토리의 존재를 확인하고 존재하지 않는 경우 생성


388

나는 종종 많은 출력을 생성하는 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
무작위로 생성 된 이름으로 임시 디렉토리를 만들고 이름을 반환하는 R 함수를 보았습니다. 임시 파일을 만드는 비슷한 파일이 있다고 생각합니다. 그것들을 직접 찾을 수는 없지만 Databel 패키지 ( cran.r-project.org/web/packages/DatABEL/index.html )에는 get_temporary_file_name 기능이 있습니다.
PaulHurleyuk

42
setwd()R 코드에서는 절대로 사용해서는 안됩니다. 더 이상 컴퓨터간에 코드를 쉽게 이동할 수 없기 때문에 작업 디렉토리를 사용한다는 아이디어를 잃게됩니다.
hadley

6
@hadley 흥미로운 주제를 숙고하고 같은 방법으로 다른 방법에 대한 귀하의 생각에 감사드립니다. 직장에서 모든 컴퓨터는 동일한 네트워크에 동기화되므로 파일 경로가 일관됩니다. 그렇지 않은 경우 스크립트 이식성보다 처리해야 할 문제가 더 큽니다. 이 특정 예에서 저는 국립 공원 주변에서 2 년 동안 운반 될 기계에로드 될 스크립트를 작성했습니다. 이 스크립트는 로컬 SQL 인스턴스에서 데이터를 가져 와서 일부 처리를 수행하고 .csv를 추출합니다. 최종 제품은 .bat최종 사용자가 수정할 필요가없는 파일입니다.
체이스

@Chase 그러나 setwd네트워크 경로로 작업 할 필요는 없습니다 . 결과를 저장하고 현재 경로 (R 세션이 시작될 때 설정된 경로)로 작업 할 경로 만 제공하면됩니다. 또는 원하는 작업 디렉토리로 R을 시작하십시오.
Marek

5
네. 또는 parametrize out_dir <- "path/to/output/directory"후를 사용하십시오 write.table(file = file.path(out_dir,"table_1.csv"), ...). 심지어 out_file <- function(fnm) file.path("path/to/output/directory", fnm)다음 write.table(file = out_file("table_1.csv"), ...)(네트워크 드라이브로 작업 할 때 내가 사용하는 비슷한 방법).
Marek

답변:


403

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

58
이를 사용 showWarnings = FALSE하면 디렉토리를 작성할 수 없다는 등의 다른 경고도 숨겨집니다.
zelanix

5
^ 하나의 특정 경고 만 억제하는 방법이 있습니까?
Bas

2
안녕하세요, 폴더 test1에 있고 test2 안에 test2 안에있는 것처럼 중첩 된 디렉토리를 만들고 싶습니다 ... 그러나 지금은 문제에 직면하고 있습니다. directory1이 종료되지 않아도 디렉토리의 3 레벨을 만들 수있는 방법이 있습니까 ??
Praveen Kesani

10
@PraveenKesani 당신이 찾고있는 것 dir.create("test1/test2/test3/", recursive=TRUE)입니까?
학장.

6
@Bas 응답이 늦었지만 suppressWarnings(<statement>)해당 내용에 대한 경고는 표시 하지 않습니다.
Ram RS

163

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

9
ifelse()벡터화되지 않은 분기 에 사용 하는 것은 좋지 않습니다 .
리오넬 헨리

2
@Bas는 벡터화 된 무언가가 발생하는 것처럼 코드가 잘못 읽히기 때문입니다. |스칼라 대신 벡터화 를 사용하는 것과 같습니다 ||. 작동하지만 나쁜 습관입니다.
리오넬 헨리

1
오 젠장, 그래서 if 문을 사용하여 잘못하여 if 문을 잘못 사용 |하여 벡터화가 ||때로는 작동하지 않는 이유 입니까? 나는 이것이 주제가 아니라는 것을 알고 있지만 너무 찾기가 열망합니다. 벡터화에 대한 자세한 내용을 알아 보겠습니다. 감사합니다
Bas

4
우리가 피해야한다면 이것을하는 가장 좋은 방법은 ifelse무엇입니까?
KillerSnail

6
if and else;) 사용
Lionel Henry

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
}

또한 ~/foo존재하지 않는 경우을 dir.create('~/foo/bar')지정하지 않으면 호출 이 실패합니다 recursive = TRUE.


3
paste (...) vs file.path (mainDir, subDir)을 사용하는 이유가 있습니까? 또한 path <-file.path (mainDir, subDir)을 수행하면 if 문을 더 읽기 쉽도록 5 번 재사용 할 수 있습니다.
MikeF

14

다음은 간단한 check 이며 존재하지 않는 경우 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!")
}

9

디렉토리의 존재를 테스트하기 위해 file.exists ()를 사용하는 것은 원래 게시물의 문제입니다. subDir에 경로가 아닌 기존 파일의 이름이 포함 된 경우 file.exists ()는 TRUE를 반환하지만 파일을 가리 키도록 작업 디렉토리를 설정할 수 없기 때문에 setwd () 호출이 실패합니다.

subDir이 기존 디렉토리 인 경우 "TRUE"를 반환하고, subDir이 기존 파일이거나 존재하지 않는 파일 또는 디렉토리 인 경우 FALSE를 반환하는 file_test (op = "-d", 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))

이 솔루션은 작업 디렉토리를 사용자가 제어합니다.


8

R 2.15.3에 문제가있어서 공유 네트워크 드라이브에서 반복적으로 트리 구조를 만들려고 할 때 권한 오류가 발생합니다.

이 이상한 점을 극복하기 위해 수동으로 구조를 만듭니다.

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

mkdirs("H:/foo/bar")

5

짧막 한 농담:

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

2

경로가 유효한 디렉토리인지 확인하려면 다음을 시도하십시오.

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

file.info 끝에 슬래시를 신경 쓰지 않습니다.

file.existsWindows에서 슬래시로 끝나고 디렉토리없이 성공하면 디렉토리에 대해 실패합니다. 따라서 경로가 디렉토리인지 판별하는 데 사용할 수 없습니다.

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

이 답변에 대해 무엇이 잘못 되었습니까 ( dir.create()일부 제외)? 진술이 잘못되었거나 당면한 문제를 해결하는 데 도움이되지 않는 것으로 간주됩니까?
mschilli
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.