507 Stimmen

Ordnerverwaltung mit r: Überprüfen Sie das Vorhandensein eines Verzeichnisses und erstellen Sie es, wenn es nicht existiert.

Ich finde oft, dass ich R-Skripte schreibe, die eine Menge Output generieren. Ich finde es sauberer, diesen Output in seinem eigenen Verzeichnis(zu) platzieren. Was ich unten geschrieben habe, überprüft die Existenz eines Verzeichnisses und wechselt dorthin oder erstellt das Verzeichnis und wechselt dann dorthin. Gibt es einen besseren Weg, dies anzugehen?

mainDir <- "c:/pfad/zum/hauptverzeichnis"
subDir <- "outputVerzeichnis"

if (file.exists(subDir)){
    setwd(file.path(mainDir, subDir))
} else {
    dir.create(file.path(mainDir, subDir))
    setwd(file.path(mainDir, subDir))

}

1 Stimmen

Ich bin mir sicher, dass es eine R-Funktion gibt, die ein temporäres Verzeichnis mit einem zufällig generierten Namen erstellt und den Namen zurückgibt. Ich glaube, es gibt eine ähnliche Funktion, die eine temporäre Datei erstellt. Ich kann sie gerade nicht finden, aber das Databel-Paket (cran.r-project.org/web/packages/DatABEL/index.html) hat eine Funktion get_temporary_file_name.

65 Stimmen

Du solltest nie setwd() im R-Code verwenden - es untergräbt im Grunde genommen die Idee der Verwendung eines Arbeitsverzeichnisses, weil du deinen Code nicht mehr leicht zwischen Computern verschieben kannst.

7 Stimmen

@hadley Interessantes Thema zum Nachdenken, ich würde Ihre Gedanken zu anderen Methoden zum selben Zweck schätzen. Bei der Arbeit sind alle Computer mit demselben Netzwerk synchronisiert, sodass Dateipfade konsistent sind. Wenn sie es nicht sind, haben wir größere Probleme zu lösen als die Tragbarkeit eines Skripts. In diesem speziellen Beispiel habe ich ein Skript geschrieben, das auf einer Maschine geladen wird, die zwei Jahre lang in unseren Nationalparks herumgetragen wird. Dieses Skript wird Daten aus einer lokalen SQL-Instanz abrufen, einige Verarbeitungen durchführen und eine .csv-Datei ausgeben. Das Endprodukt wird eine .bat Datei sein, die der Endbenutzer nie ändern muss.

13voto

user425678 Punkte 690

Ich hatte ein Problem mit R 2.15.3, bei dem ich beim Versuch, eine Baumstruktur rekursiv auf einem freigegebenen Netzlaufwerk zu erstellen, eine Berechtigungsfehlermeldung erhalten würde.

Um dieser Eigenart aus dem Weg zu gehen, habe ich die Struktur manuell erstellt;

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

mkdirs("H:/foo/bar")

11voto

G Poole Punkte 101

Die Verwendung von file.exists(), um das Vorhandensein des Verzeichnisses zu testen, ist ein Problem im Originalbeitrag. Wenn subDir den Namen einer vorhandenen Datei enthielte (anstelle eines einfachen Pfads), würde file.exists() TRUE zurückgeben, aber der Aufruf von setwd() würde fehlschlagen, weil man das Arbeitsverzeichnis nicht auf eine Datei setzen kann.

Ich würde die Verwendung von file_test(op="-d", subDir) empfehlen, das "TRUE" zurückgibt, wenn subDir ein vorhandenes Verzeichnis ist, aber "FALSE", wenn subDir eine vorhandene Datei oder eine nicht vorhandene Datei oder Verzeichnis ist. Ebenso kann das Testen auf eine Datei mit op="-f" erreicht werden.

Zusätzlich, wie in einem anderen Kommentar beschrieben, ist das Arbeitsverzeichnis Teil der R-Umgebung und sollte vom Benutzer kontrolliert werden, nicht von einem Skript. Skripte sollten idealerweise die R-Umgebung nicht ändern. Um dieses Problem zu lösen, könnte ich options() verwenden, um ein global verfügbares Verzeichnis zu speichern, in dem ich all meine Ausgaben haben möchte.

Also, betrachten Sie die folgende Lösung, wobei someUniqueTag nur ein vom Programmierer definierter Präfix für den Optionnamen ist, was es unwahrscheinlich macht, dass bereits eine Option mit dem gleichen Namen existiert. (Zum Beispiel, wenn Sie ein Paket mit dem Namen "filer" entwickeln würden, könnten Sie filer.mainDir und filer.subDir verwenden).

Der folgende Code würde verwendet werden, um Optionen festzulegen, die später in anderen Skripts verwendet werden können (um so die Verwendung von setwd() in einem Skript zu vermeiden) und um das Verzeichnis bei Bedarf zu erstellen:

mainDir = "c:/Pfad/zum/hauptverzeichnis"
subDir = "outputVerzeichnis"

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("Der Pfad kann nicht erstellt werden, weil bereits eine Datei mit diesem Namen existiert.")
  } else {
    dir.create(file.path(mainDir, subDir))
  }
}

Dann, in einem beliebigen nachfolgenden Skript, das eine Datei in subDir manipulieren müsste, könnten Sie etwas wie das folgende verwenden:

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

Diese Lösung lässt das Arbeitsverzeichnis unter der Kontrolle des Benutzers.

8voto

Amy M Punkte 811

Ich weiß, diese Frage wurde vor einiger Zeit gestellt, aber falls nützlich, das here Paket ist wirklich hilfreich, um spezifische Dateipfade nicht angeben zu müssen und den Code portabler zu machen. Es definiert automatisch Ihr Arbeitsverzeichnis als das Verzeichnis, in dem sich Ihre .Rproj Datei befindet, sodass oft folgendes ausreicht, ohne den Dateipfad zu Ihrem Arbeitsverzeichnis definieren zu müssen:

library(here)

if (!dir.exists(here(outputDir))) {dir.create(here(outputDir))}

4voto

Hugh Punkte 14676

Paket hutils (das ich erstellt habe) enthält die Funktionen provide.dir(path) und provide.file(path) zur Überprüfung der Verzeichnisse/Dateien unter path, wobei sie erstellt werden, wenn sie fehlen.

0 Stimmen

Schöne Arbeit - sehr sauber ohne all die "wenn dir/Datei existiert" Überprüfungen

3voto

user3807179 Punkte 49

Um herauszufinden, ob ein Pfad ein gültiges Verzeichnis ist, versuchen Sie es mit:

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

file.info kümmert sich nicht um einen Schrägstrich am Ende.

file.exists scheitert auf Windows für ein Verzeichnis, wenn es mit einem Schrägstrich endet, und es gelingt ohne ihn. Daher kann dies nicht verwendet werden, um festzustellen, ob es sich um ein Verzeichnis handelt.

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

0 Stimmen

Was ist falsch an dieser Antwort (abgesehen davon, dass der dir.create()-Teil fehlt)? Sind die Aussagen falsch oder einfach nur nicht hilfreich zur Lösung der Frage?

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X