Dizinin varlığını kontrol edin ve yoksa oluşturun


388

Sık sık kendimi çok fazla çıktı üreten R komut dosyaları yazarken buluyorum. Bu çıktıyı kendi dizin (ler) ine koymak daha temiz buluyorum. Aşağıda yazdıklarım bir dizinin varlığını kontrol edecek ve dizine geçecek ya da dizini oluşturacak ve dizine geçecektir. Buna yaklaşmanın daha iyi bir yolu var mı?

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
Rastgele oluşturulmuş bir adla geçici bir dizin oluşturan ve adı döndüren bir R işlevi gördüm eminim. Temp dosyası oluşturan benzer bir dosya olduğunu düşünüyorum. Onları hazırlıksız bulamıyorum, ancak Databel paketinin ( cran.r-project.org/web/packages/DatABEL/index.html ) get_temporary_file_name işlevi var.
PaulHurleyuk

42
Asla setwd()R kodunda kullanmamalısınız - kodunuzu bilgisayarlar arasında kolayca taşıyamayacağınız için temelde bir çalışma dizini kullanma fikrini yener.
hadley

6
@hadley düşünmek için ilginç bir konu, aynı amaçla diğer yöntemler hakkındaki düşüncelerinizi takdir ediyorum. İş yerinde, tüm bilgisayarlar aynı ağla senkronize edilir, böylece dosya yolları tutarlı olur. Değilse, bir komut dosyasının taşınabilirliğinden daha büyük sorunlarımız var. Bu özel örnekte, 2 yıl boyunca milli parklarımızda taşınacak bir makineye yüklenecek bir senaryo yazıyordum. Bu komut dosyası yerel bir SQL örneğinden veri alır, bazı işlemler yapar ve bir .csv tükürür. Son ürün .bat, son kullanıcının asla değiştirmek zorunda kalmayacağı bir dosya olacaktır.
Chase

@Chase Ancak setwdağ yollarıyla çalışmanıza gerek yoktur . Sonuçları kaydetmek ve halen geçerli yolla (R oturumu başladığında kurulan yol) çalışmak için yollar sağlamanız yeterlidir. Ya da R'yi çalışma dizini ile başlatın.
Marek

5
Evet. Veya parametrelendirin out_dir <- "path/to/output/directory"ve kullanın write.table(file = file.path(out_dir,"table_1.csv"), ...). Hatta out_file <- function(fnm) file.path("path/to/output/directory", fnm)daha sonra write.table(file = out_file("table_1.csv"), ...)(ağ sürücüleri ile çalışırken kullanabileceğim benzer yöntemi).
Marek

Yanıtlar:


403

Kullanım showWarnings = FALSE:

dir.create(file.path(mainDir, subDir), showWarnings = FALSE)
setwd(file.path(mainDir, subDir))

dir.create()dizin zaten varsa çökmez, sadece bir uyarı yazdırır. Dolayısıyla, uyarıları görmekle yaşayabiliyorsanız, bunu yapmakla ilgili bir sorun yoktur:

dir.create(file.path(mainDir, subDir))
setwd(file.path(mainDir, subDir))

58
showWarnings = FALSEBunu kullanırken , dizinin oluşturulamaz olması gibi diğer uyarıları da gizleyeceğini unutmayın.
zelanix

5
^ Sadece bir uyarıyı bastırmanın bir yolu var mı?
Bas

2
Merhaba, ben klasör test1 içinde o zaman içinde test2 içinde test2 ... gibi ben iç içe dizin oluşturmak istiyorum ... ama şu anda sorunla karşı karşıya. Dizin1 çıkmasa bile ben 3 dizin düzeyi oluşturabilirsiniz bir yolu var mı ??
Praveen Kesani

10
@PraveenKesani Aradığın şey bu dir.create("test1/test2/test3/", recursive=TRUE)mu?
dekan.

6
@Bas Gerçekten geç yanıt ama suppressWarnings(<statement>)sadece bu ifade için uyarıları bastırır.
Ram RS

163

16 Nisan 2015 itibariyle, piyasaya sürülmesiyle birlikte R 3.2.0yeni bir işlev var dir.exists(). Bu işlevi kullanmak ve yoksa dizini oluşturmak için aşağıdakileri kullanabilirsiniz:

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

FALSEDizin zaten varsa veya oluşturulamıyorsa ve TRUEyoksa , ancak başarıyla oluşturulmuşsa bu geri döner .

Dizinin mevcut olup olmadığını kontrol etmek için şunu kullanabilirsiniz:

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

9
ifelse()Vektörize olmayan dallanma için kullanmak iyi bir uygulama değildir .
Lionel Henry

2
@Bas çünkü kodunuz hatalı bir şekilde vectorized bir şey oluyormuş gibi okuyor. |Skaler yerine vectorize kullanmak gibidir ||. Çalışıyor ama kötü bir uygulama.
Lionel Henry

1
Kahretsin, bu yüzden if ifadelerimi kullanarak da yanlış yapıyorum |, vektörleşme ||bazen çalışmamasının nedeni mi? Bunun konu dışı olduğunu biliyorum ama öğrenmeye çok hevesliyim. Ben defo gidip vektörleşme hakkında daha fazla bilgi edeceğim. Teşekkürler
Bas

4
Bundan kaçınmamız gerekirse bunu yapmanın en iyi yolu ifelsenedir?
KillerSnail

6
if ve else kullanarak;)
Lionel Henry

17

Genel mimari açısından dizin oluşturma ile ilgili olarak aşağıdaki yapıyı tavsiye ederim. Bu, çoğu olası sorunu kapsayacak ve dizin oluşturma ile ilgili diğer sorunlar dir.createçağrı tarafından algılanacaktır .

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
}

Ayrıca yoksa ~/foo, dir.create('~/foo/bar')siz belirtmedikçe yapılacak bir çağrının başarısız olacağını da unutmayın recursive = TRUE.


3
paste (...) vs file.path (mainDir, subDir) kullanmanın bir nedeni var mı? Ayrıca <- file.path (mainDir, subDir) yolunu yaptıysanız, if ifadelerini daha okunabilir hale getirmek için 5 kez yeniden kullanabilirsiniz.
MikeF

14

İşte basit bir kontrol , ve mevcut değilse dir oluşturur:

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

Dizinin varlığını test etmek için file.exists () kullanımı, orijinal gönderide bir sorundur. SubDir varolan bir dosyanın adını (yalnızca yol yerine) içeriyorsa, file.exists (), TRUE değerini döndürür, ancak çalışma dizinini bir dosyayı gösterecek şekilde ayarlayamadığınız için setwd () çağrısı başarısız olur.

SubDir varolan bir dizinse "TRUE", ancak subDir varolan bir dosya veya varolmayan bir dosya veya dizinse FALSE döndürecek olan file_test (op = "- d", subDir) kullanımını öneririm. Benzer şekilde, bir dosya kontrolü op = "- f" ile yapılabilir.

Ayrıca, başka bir açıklamada açıklandığı gibi, çalışma dizini R ortamının bir parçasıdır ve bir komut dosyası tarafından değil, kullanıcı tarafından denetlenmelidir. Scriptler ideal olarak R ortamını değiştirmemelidir. Bu sorunu gidermek için, tüm çıktımı istediğim global olarak kullanılabilir bir dizini saklamak için options () kullanabilirsiniz.

Bu nedenle, someUniqueTag öğesinin seçenek adı için yalnızca programcı tanımlı bir önek olduğu aşağıdaki çözümü göz önünde bulundurun; (Örneğin, "filer" adlı bir paket geliştiriyorsanız, filer.mainDir ve filer.subDir kullanabilirsiniz).

Aşağıdaki kod, daha sonra diğer komut dosyalarında kullanılabilecek seçenekleri ayarlamak (böylece bir komut dosyasında setwd () kullanmaktan kaçınmak) ve gerekirse klasörü oluşturmak için kullanılır:

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

Ardından, subDir'de bir dosyayı işlemek için gereken herhangi bir komut dosyasında aşağıdaki gibi bir şey kullanabilirsiniz:

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

Bu çözüm, çalışma dizinini kullanıcının denetiminde bırakır.


8

Paylaşılan bir ağ sürücüsünde özyinelemeli bir ağaç yapısı oluşturmaya çalışırken bir izin hatası alacağım R 2.15.3 ile ilgili bir sorunum vardı.

Bu tuhaflığın üstesinden gelmek için yapıyı el ile oluşturuyorum;

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

mkdirs("H:/foo/bar")

5

Tek astarı:

if (!dir.exists(output_dir)) {dir.create(output_dir)}

Misal:

dateDIR <- as.character(Sys.Date())
outputDIR <- file.path(outD, dateDIR)
if (!dir.exists(outputDIR)) {dir.create(outputDIR)}

2

Bir yolun geçerli bir dizin olup olmadığını öğrenmek için şunu deneyin:

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

file.info sonunda eğik çizgi umurunda değil.

file.existsWindows'da bir eğik çizgi ile biterse ve onsuz başarılı olursa bir dizin için başarısız olur. Bu nedenle, bir yolun dizin olup olmadığını belirlemek için kullanılamaz.

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

Bu cevapta yanlış olan ne dir.create()? İfadeler yanlış mı yoksa eldeki soruyu çözmek için yararlı değil mi?
mschilli
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.