Bestimmen Sie den Pfad des ausführenden Skripts

255

Ich habe ein Skript namens foo.R, das ein anderes Skript enthält other.R, das sich im selben Verzeichnis befindet:

#!/usr/bin/env Rscript
message("Hello")
source("other.R")

Aber ich möchte Rdas finden, other.Regal was das aktuelle Arbeitsverzeichnis ist.

Mit anderen Worten, foo.Rmuss seinen eigenen Weg kennen. Wie kann ich das machen?

Frank
quelle
2
Nein. :( Ich habe keine Lösung gesehen, die tatsächlich funktioniert. Abgesehen von der Problemumgehung, das Verzeichnis einfach zu übergeben oder eine Umgebungsvariable zu verwenden.
Frank
3
Es wäre erstaunlich, Skripte auch von R neofites vollständig portierbar und ausführbar zu machen!
Etienne Low-Décarie
4
Es scheint, als müssten Sie bei allen Antworten den Pfad irgendwann eingeben (zumindest um die Datei zu beschaffen)! Es wäre großartig, wenn Sie jemandem einen komprimierten Ordner senden könnten und das Ausführen einer beliebigen R-Skriptdatei in diesem Ordner aus diesem Ordner lesen und in diesem Ordner speichern würde.
Etienne Low-Décarie
10
Diese einzige Ausgabe könnte tatsächlich der Grund sein, warum ich am
Giacomo
5
@giac_man, ich glaube, R ist voll von Hunderten von winzigen Problemen wie diesen, die allesamt dazu führen, dass es sehr schwierig ist, darin zu arbeiten.
Michael Barton

Antworten:

102

Hier gibt es eine einfache Lösung für das Problem. Dieser Befehl:

script.dir <- dirname(sys.frame(1)$ofile)

Gibt den Pfad der aktuellen Skriptdatei zurück. Es funktioniert, nachdem das Skript gespeichert wurde.

this.is.not.a.nick
quelle
4
Es funktioniert nicht bei mir. Ich führe R in Windows aus. Irgendeine Idee?
Ehsan88
4
Habe den gleichen Fehler bekommen, mit einem gespeicherten Skript und frisch installiert und R 3.2.0 unter Windows ausgeführt ...
RalfB
27
Dieser Fehler tritt auf, wenn Sie versuchen, dirname(sys.frame(1)$ofile)direkt von Rstudio aus auszuführen. Es funktioniert in Ordnung, wenn das Skript mit source ("other.R") ausgeführt wird und sich darin dirname(sys.frame(1)$ofile)befindet "other.R".
Murta
4
Beim Aufrufen als Skript mit rscript.exe, dh ohne Verwendung von source (), wurde der Fehler "Nicht so viele Frames auf dem Stapel" angezeigt.
Mark Adamson
3
Ich NULLgeliere, wenn dies in Server.R platziert wird, wenn glänzend verwendet
Paul
75

Mit der commandArgsFunktion können Sie alle Optionen abrufen, die von Rscript an den eigentlichen R-Interpreter übergeben wurden, und nach ihnen suchen --file=. Wenn Ihr Skript über den Pfad gestartet wurde oder wenn es mit einem vollständigen Pfad gestartet wurde, script.namebeginnt das Folgende mit einem '/'. Andernfalls muss es relativ zu sein cwdund Sie können die beiden Pfade zusammenfassen, um den vollständigen Pfad zu erhalten.

Bearbeiten: Es hört sich so an, als würden Sie nur das script.nameObige benötigen und die letzte Komponente des Pfades entfernen. Ich habe das nicht benötigte cwd()Beispiel entfernt, das Hauptskript bereinigt und mein other.R. Speichern Sie dieses Skript und das other.RSkript einfach im selben Verzeichnis chmod +xund führen Sie das Hauptskript aus.

main.R :

#!/usr/bin/env Rscript
initial.options <- commandArgs(trailingOnly = FALSE)
file.arg.name <- "--file="
script.name <- sub(file.arg.name, "", initial.options[grep(file.arg.name, initial.options)])
script.basename <- dirname(script.name)
other.name <- file.path(script.basename, "other.R")
print(paste("Sourcing",other.name,"from",script.name))
source(other.name)

other.R :

print("hello")

Ausgabe :

burner@firefighter:~$ main.R
[1] "Sourcing /home/burner/bin/other.R from /home/burner/bin/main.R"
[1] "hello"
burner@firefighter:~$ bin/main.R
[1] "Sourcing bin/other.R from bin/main.R"
[1] "hello"
burner@firefighter:~$ cd bin
burner@firefighter:~/bin$ main.R
[1] "Sourcing ./other.R from ./main.R"
[1] "hello"

Ich glaube, das ist es, wonach Dehmann sucht.

Feuer unterdrücken
quelle
Was ist mit dem Downmod?
Suppressingfire
2
Ich habe mich modifiziert, weil Ihre Technik nicht so funktioniert, sourcewie ich dachte, dass das OP es wollte - aber vielleicht habe ich seine / ihre Anforderung falsch verstanden. Aber ich kann nicht un-downmod :( Entschuldigung!
Hadley
Aber eigentlich funktioniert es gut mit der Quelle! Nur source (other.name) und es funktioniert richtig.
Suppressingfire
3
Für die Pfadverkettung besser zu verwendenother.name <- file.path(script.basename, "other.R")
Jason
1
Wenn ich versuche, commandArgs(trailingOnly = FALSE)in server.R in einer glänzenden Anwendung zu laufen, bekomme ich [1] "RStudio" "--interactive". Keine Informationen zu dem Verzeichnis, aus dem es aufgerufen wurde.
Paul
57

Ich konnte die Lösung von Suppressingfire nicht zum Laufen bringen, wenn ich von der R-Konsole aus "quelle".
Ich konnte Hadleys Lösung nicht zum Laufen bringen, wenn ich Rscript verwendete.

Beste aus beiden Welten?

thisFile <- function() {
        cmdArgs <- commandArgs(trailingOnly = FALSE)
        needle <- "--file="
        match <- grep(needle, cmdArgs)
        if (length(match) > 0) {
                # Rscript
                return(normalizePath(sub(needle, "", cmdArgs[match])))
        } else {
                # 'source'd via R console
                return(normalizePath(sys.frames()[[1]]$ofile))
        }
}
Dampfer25
quelle
6
Ich mag das, weil es mit beiden Rscriptund source()innerhalb von R funktioniert . Ich würde vorschlagen, es normalizePath()mit beiden Versionen zu tun , damit es in beiden Fällen den vollständigen Pfad angibt.
wch
1
Dies ist das einzige, was funktioniert hat. Beachten Sie, dass dies library(base)eine Weile
gedauert hat
2
Sie, Sir, bekommen meine Stimme, denn dies ist die Lösung, die für mich funktioniert hat
Vince W.
1
Wenn dies jemand hilft, für den ursprünglichen Beitrag, das würde bedeuten , source(file.path(dirname(thisFile()), "other.R"))in foo.R. Das funktioniert bei mir.
Kim
Ein Problem. Angenommen, in RStudio gebe ich an, main.Rwelche Quellen helper.Rwelche Anrufe tätigen thisFile(). Es wird den Pfad von main.Rstatt abrufen helper.R. Irgendwelche Tipps hier?
Wassadamo
37
frame_files <- lapply(sys.frames(), function(x) x$ofile)
frame_files <- Filter(Negate(is.null), frame_files)
PATH <- dirname(frame_files[[length(frame_files)]])

Frag mich aber nicht, wie es funktioniert, denn ich habe vergessen: /

Hadley
quelle
2
In welchem ​​Kontext funktioniert das? print (sys.frames ()) wird beim Ausführen mit NULL angezeigt.
Unterdrückungsfeuer
1
@Suppressingfire: Gibt sys.framesdie Umgebungen des Aufrufstapels zurück, sodass es nur dann wirklich Sinn macht, wenn es von einer Funktion aufgerufen wird. Versuchen Sie es z foo <- function() {bar <- function() print(sys.frames()); bar()}; foo(). Ich kann den Code von @ hadley jedoch nicht herausfinden, da Umgebungen kein ofileMitglied haben.
Richie Cotton
1
Sie haben die Datei in beziehen - dh wenn ich diesen Code speichern dann ausführen source("~/code/test.r"), PATHwird festgelegt werden ~/desktop. Wenn Sie es nur auf der obersten Ebene auswerten, wird NULL zurückgegeben.
Hadley
4
Dies beantwortet meine Frage nicht. Ich muss die Datei "other.R" automatisch finden. x$ofileist undefiniert, frame_filesist also leer.
Frank
@ Hadley, sehr nützlicher Code. Ich konnte die Dienstprogrammfunktion "Aktuelles Skript neu laden" verallgemeinern, die ich fast allen Skripten hinzufüge, wenn sie sich in der aktiven Entwicklung befinden. RScript Reloader
Sim
29

Das funktioniert bei mir

library(rstudioapi)    
rstudioapi::getActiveDocumentContext()$path
ColinTea
quelle
4
Dies funktioniert wohl nur innerhalb von RStudio. Ich versuche es vom Terminal aus Error: RStudio not running.
Ista
Insbesondere funktioniert es, wenn es von einem R-Skript in R Studio ausgeführt wird. Selbst auf der Konsole in RStudio wird es ""in meinem Fall nicht das richtige Ergebnis geben
Kay
Dies funktioniert, wenn Sie interaktiv in Rstudio ausgeführt werden, solange Sie das Dokument nicht im Fokus ändern . Wenn Sie Zeilen zur Ausführung senden und dann während der Ausführung zu einem anderen Dokument wechseln, wird der Pfad zum anderen Dokument zurückgegeben.
Patrick vor
26

Die Antwort von Rakensi aus dem Pfad eines R-Skripts ist meiner Meinung nach die korrekteste und wirklich brillanteste. Dennoch ist es immer noch ein Hack mit einer Dummy-Funktion. Ich zitiere es hier, damit es von anderen leichter gefunden wird.

sourceDir <- getSrcDirectory (Funktion (Dummy) {Dummy})

Dies gibt das Verzeichnis der Datei an, in der die Anweisung platziert wurde (in der die Dummy-Funktion definiert ist). Es kann dann verwendet werden, um das Arbeitsverzeichnis festzulegen und relative Pfade zu verwenden, z

setwd(sourceDir)
source("other.R")

oder um absolute Pfade zu erstellen

 source(paste(sourceDir, "/other.R", sep=""))
Manschette
quelle
1
Für mich war Ihre Lösung die beste. Insbesondere, weil es auf eine Shiny-App angewendet werden könnte und die auf Link nicht.
Jcarlos
1
Hier ist das getSrcDirectory utils :: getSrcDirectory
RubenLaguna
5
Dies mag unter Linux / Mac gut funktionieren, aber in einer interaktiven RStudio-Sitzung unter Windows hat es bei mir nicht funktioniert. sourceDirwar leer.
Contango
1
@Contango auf einem interaktiven Terminal, es gibt keinen Weg !!! Sie möchten den Pfad zu einer Datei.
pommedeterresautee
1
Ich bekomme character(0). Vorschläge?
Abalter
16

Mein alles in einem! (--01 / 09/2019 aktualisiert, um mit RStudio Console umzugehen)

#' current script file (in full path)
#' @description current script file (in full path)
#' @examples
#' works with Rscript, source() or in RStudio Run selection, RStudio Console
#' @export
ez.csf <- function() {
    # http://stackoverflow.com/a/32016824/2292993
    cmdArgs = commandArgs(trailingOnly = FALSE)
    needle = "--file="
    match = grep(needle, cmdArgs)
    if (length(match) > 0) {
        # Rscript via command line
        return(normalizePath(sub(needle, "", cmdArgs[match])))
    } else {
        ls_vars = ls(sys.frames()[[1]])
        if ("fileName" %in% ls_vars) {
            # Source'd via RStudio
            return(normalizePath(sys.frames()[[1]]$fileName))
        } else {
            if (!is.null(sys.frames()[[1]]$ofile)) {
            # Source'd via R console
            return(normalizePath(sys.frames()[[1]]$ofile))
            } else {
                # RStudio Run Selection
                # http://stackoverflow.com/a/35842176/2292993
                pth = rstudioapi::getActiveDocumentContext()$path
                if (pth!='') {
                    return(normalizePath(pth))
                } else {
                    # RStudio Console
                    tryCatch({
                            pth = rstudioapi::getSourceEditorContext()$path
                            pth = normalizePath(pth)
                        }, error = function(e) {
                            # normalizePath('') issues warning/error
                            pth = ''
                        }
                    )
                    return(pth)
                }
            }
        }
    }
}
Jerry T.
quelle
Funktioniert nicht mit interaktiven R-Sitzungen. Ich erhalte: `` `> source (" csf.R ")> csf () Fehler: RStudio läuft
nicht`
Das ist toll. Kann jemand ein Paket machen?
Joe Flack
Dies funktioniert, wenn Sie interaktiv in Rstudio ausgeführt werden, solange Sie das Dokument nicht im Fokus ändern. Wenn Sie Zeilen zur Ausführung senden und dann während der Ausführung zu einem anderen Dokument wechseln, wird der Pfad zum anderen Dokument zurückgegeben.
Patrick vor
13

Eine abgespeckte Variante von Supressingfires Antwort:

source_local <- function(fname){
    argv <- commandArgs(trailingOnly = FALSE)
    base_dir <- dirname(substring(argv[grep("--file=", argv)], 8))
    source(paste(base_dir, fname, sep="/"))
}
Momeara
quelle
Dies funktionierte nicht rekursiv; Die von mir bezogene Datei sucht nach einer Datendatei (jedoch im falschen Verzeichnis).
Die unfun Katze
11

Das funktioniert bei mir. Greift es einfach aus den Befehlszeilenargumenten heraus, entfernt den unerwünschten Text, macht einen Verzeichnisnamen und erhält schließlich den vollständigen Pfad daraus:

args <- commandArgs(trailingOnly = F)  
scriptPath <- normalizePath(dirname(sub("^--file=", "", args[grep("^--file=", args)])))
eddi
quelle
8

Ich habe die Antworten auf diese Frage in eine neue Funktion thisfile()in rprojroot eingepackt und erweitert . Funktioniert auch zum Stricken mit knitr.

krlmlr
quelle
6

Ich mochte die Lösung von steamer25, da sie für meine Zwecke am robustesten erscheint. Beim Debuggen in RStudio (in Windows) wurde der Pfad jedoch nicht richtig festgelegt. Der Grund dafür ist, dass bei der Festlegung eines Haltepunkts in RStudio für die Beschaffung der Datei ein alternativer Befehl "Debug-Quelle" verwendet wird, mit dem der Skriptpfad etwas anders festgelegt wird. Hier ist die endgültige Version, die ich derzeit verwende und die dieses alternative Verhalten in RStudio beim Debuggen berücksichtigt:

# @return full path to this script
get_script_path <- function() {
    cmdArgs = commandArgs(trailingOnly = FALSE)
    needle = "--file="
    match = grep(needle, cmdArgs)
    if (length(match) > 0) {
        # Rscript
        return(normalizePath(sub(needle, "", cmdArgs[match])))
    } else {
        ls_vars = ls(sys.frames()[[1]])
        if ("fileName" %in% ls_vars) {
            # Source'd via RStudio
            return(normalizePath(sys.frames()[[1]]$fileName)) 
        } else {
            # Source'd via R console
            return(normalizePath(sys.frames()[[1]]$ofile))
        }
    }
}
Aprstar
quelle
Quelle in Rstudio gab ofile für mich, aber debugSource gab fileName, damit Ihre Lösung gut funktioniert, aber die Codekommentare sind in meinem Fall nicht ganz richtig
Mark Adamson
6

Ich habe fast alles aus dieser Frage heraus versucht: Pfad eines R-Skripts abrufen , Pfad des aktuellen Skripts abrufen , Speicherort der aktuellen R-Datei suchen und R-Befehl zum Festlegen des Arbeitsverzeichnisses auf den Speicherort der Quelldatei in Rstudio , aber am Ende fand ich mich manuell Durchsuchen der CRAN-Tabelle und gefunden

scriptName Bibliothek

current_filename()Dies bietet eine Funktion, die beim Sourcing in RStudio und auch beim Aufrufen über die ausführbare Datei R oder RScript den richtigen vollständigen Pfad des Skripts zurückgibt.

Bojan P.
quelle
2
Package ‘scriptName’ was removed from the CRAN repository.- was jetzt? : o
Bojan P.
3

Ich hatte auch dieses Problem und keine der oben genannten Lösungen funktionierte für mich. Vielleicht mit dem sourceoder solchen Dingen, aber es war nicht klar genug.

Ich fand diese für mich elegante Lösung:

paste0(gsub("\\", "/", fileSnapshot()$path, fixed=TRUE),"/")

Das Wichtigste dabei ist, fileSnapshot()dass Sie viele Informationen über eine Datei erhalten. Es wird eine Liste mit 8 Elementen zurückgegeben. Wenn Sie pathals Listenelement auswählen , wird der Pfad \\als Trennzeichen zurückgegeben, sodass der Rest des Codes nur dazu dient, dies zu ändern.

Ich hoffe das hilft.

Antoine
quelle
1
Dies funktionierte bei mir auf einem Linux-Computer nicht. Anstatt den Pfad der Datei zurückzugeben, wurde das Verzeichnis zurückgegeben, in dem ich mich gerade befand. Ich habe ein Testskript namens TEST.R mit einer Codezeile erstellt: print (fileSnapshot () $ path) Ich habe es in diesem Ordner gespeichert: / opt / home / boops / Desktop / Testfolder / TEST.RI navigierte dann zu meinem Desktop und versuchte, die Datei auszuführen: boops @ linuxserver: ~ / Desktop $ Rscript /opt/home/boops/Desktop/Testfolder/TEST.R [1 ] "/ opt / home / boops / Desktop"
Boops Boops
Hat auch bei mir nicht funktioniert. Gibt dasselbe zurück wie 'here ()', wenn die 'here'-Bibliothek verwendet wird. Es gab den Pfad zu meinem aktuell geöffneten R-Projekt zurück, aber nicht die Datei selbst, die ausgeführt wird.
Joe Flack
2

Sie können das r-Skript in ein Bash-Skript einschließen und den Pfad des Skripts als Bash-Variable wie folgt abrufen:

#!/bin/bash
     # [environment variables can be set here]
     path_to_script=$(dirname $0)

     R --slave<<EOF
        source("$path_to_script/other.R")

     EOF
ennuikiller
quelle
3
Dies setzt voraus, dass Sie den Skriptpfad haben. Sie können kein wirklich portables R-Skript erstellen, das von überall ausgeführt werden kann.
Etienne Low-Décarie
@ EtienneLow-Décarie Der Skriptpfad wird nicht benötigt, er wird von bash abgerufen. Das Hauptproblem ist, dass es kein zuverlässiger Weg ist, den Pfad zu finden. So etwas wird bevorzugt, wie in stackoverflow.com/questions/59895/… path_to_script = "$ (cd" $ (dirname "$ {BASH_SOURCE [0]}") "&& pwd)"
John Haberstroh
2

Ich mag diesen Ansatz:

this.file <- sys.frame(tail(grep('source',sys.calls()),n=1))$ofile
this.dir <- dirname(this.file)
kuna.matata
quelle
2

Ich habe das einfach selbst herausgefunden. Um die Portabilität Ihres Skripts sicherzustellen, beginnen Sie immer mit:

wd <- setwd(".")
setwd(wd)

Es funktioniert, weil "." übersetzt wie der Unix-Befehl $ PWD. Wenn Sie diese Zeichenfolge einem Zeichenobjekt zuweisen, können Sie dieses Zeichenobjekt in setwd () einfügen. Presto Ihr Code wird immer mit seinem aktuellen Verzeichnis als Arbeitsverzeichnis ausgeführt, unabhängig davon, auf welchem ​​Computer er sich befindet oder wo in der Dateistruktur er sich befindet gelegen. (Zusätzlicher Bonus: Das wd-Objekt kann mit file.path () (dh file.path (wd, "output_directory") verwendet werden, um unabhängig vom Dateipfad, der zu Ihrem benannten Verzeichnis führt, ein Standardausgabeverzeichnis zu erstellen. Dazu müssen Sie das neue Verzeichnis erstellen, bevor Sie es auf diese Weise referenzieren. Dies kann jedoch auch mit dem wd-Objekt unterstützt werden.

Alternativ führt der folgende Code genau dasselbe aus:

wd <- getwd()
setwd(wd)

Wenn Sie den Dateipfad in einem Objekt nicht benötigen, können Sie einfach:

setwd(".")
Andrew Moffat Jr.
quelle
11
Nee. Das findet das Verzeichnis des Prozesses, nicht die Datei selbst.
user1071847
Dies funktionierte bei mir unter Windows mit RStudio im interaktiven Modus.
Contango
2

Beachten Sie, dass das getopt-Paket die get_Rscript_filenameFunktion bereitstellt , die nur die hier vorgestellte Lösung verwendet, jedoch bereits in einem Standard-R-Modul für Sie geschrieben wurde, sodass Sie die Funktion "get script path" nicht in jedes Skript kopieren und einfügen müssen du schreibst.

Ryan C. Thompson
quelle
Es gibt immer NA zurück, auch wenn ich ein Skript erstelle, das seine Ausgabe druckt und dann das Skript R -e "library(getopt); testscript.R"
aufruft,
1
Wie der Name der Funktion andeutet, müssen Sie Ihr Skript mit ausführen Rscript.
Ryan C. Thompson
Ah, hoppla. Vielen Dank.
Bokov
1

Siehe findSourceTraceback()das R.utils- Paket, das

Findet alle von source () generierten 'srcfile'-Objekte in allen Aufrufrahmen. Auf diese Weise können Sie herausfinden, welche Dateien derzeit von source () gescriptet werden.

HenrikB
quelle
1

Ich hatte Probleme mit den oben genannten Implementierungen, da mein Skript von einem Symlink-Verzeichnis aus betrieben wird, oder zumindest denke ich, dass die oben genannten Lösungen für mich nicht funktioniert haben. In Anlehnung an die Antwort von @ ennuikiller habe ich mein Rscript in Bash eingewickelt. Ich setze die pwd -PPfadvariable mit , die symlinked Verzeichnisstrukturen auflöst. Übergeben Sie dann den Pfad in das Rscript.

Bash.sh

#!/bin/bash

# set path variable
path=`pwd -P`

#Run Rscript with path argument
Rscript foo.R $path

foo.R

args <- commandArgs(trailingOnly=TRUE)
setwd(args[1])
source(other.R)
Luke Singham
quelle
1

Ich würde eine Variante des Ansatzes von @ steamer25 verwenden. Der Punkt ist, dass ich es vorziehen würde, das Skript mit der letzten Quelle zu erhalten, selbst wenn meine Sitzung über Rscript gestartet wurde. Das folgende Snippet enthält, wenn es in einer Datei enthalten ist, eine Variable, thisScriptdie den normalisierten Pfad des Skripts enthält. Ich gestehe die (ab) Verwendung von source'ing, deshalb rufe ich manchmal Rscript auf und das im --fileArgument angegebene Skript liefert ein anderes Skript, das ein anderes liefert ... Eines Tages werde ich investieren, um meinen unordentlichen Code in ein Paket zu verwandeln.

thisScript <- (function() {
  lastScriptSourced <- tail(unlist(lapply(sys.frames(), function(env) env$ofile)), 1)

  if (is.null(lastScriptSourced)) {
    # No script sourced, checking invocation through Rscript
    cmdArgs <- commandArgs(trailingOnly = FALSE)
    needle <- "--file="
    match <- grep(needle, cmdArgs)
    if (length(match) > 0) {
      return(normalizePath(sub(needle, "", cmdArgs[match]), winslash=.Platform$file.sep, mustWork=TRUE))
    }
  } else {
    # 'source'd via R console
    return(normalizePath(lastScriptSourced, winslash=.Platform$file.sep, mustWork=TRUE))
  }
})()
Ailton Andrade de Oliveira
quelle
1

99% der Fälle könnten Sie einfach verwenden:

sys.calls()[[1]] [[2]]

Es funktioniert nicht für verrückte Anrufe, bei denen das Skript nicht das erste Argument ist, d source(some args, file="myscript"). H. Verwenden Sie @ hadley in diesen ausgefallenen Fällen.

Antonio
quelle
Nicht aus RStudio heraus, außer bei der Beschaffung
nJGL
1

Der Ansatz von Steamer25 funktioniert, jedoch nur, wenn der Pfad kein Leerzeichen enthält. Unter macOS gibt das zumindest so cmdArgs[match]etwas wie /base/some~+~dir~+~with~+~whitespace/für zurück /base/some\ dir\ with\ whitespace/.

Ich habe dies umgangen, indem ich das "~ + ~" durch ein einfaches Leerzeichen ersetzt habe, bevor ich es zurückgegeben habe.

thisFile <- function() {
  cmdArgs <- commandArgs(trailingOnly = FALSE)
  needle <- "--file="
  match <- grep(needle, cmdArgs)
  if (length(match) > 0) {
    # Rscript
    path <- cmdArgs[match]
    path <- gsub("\\~\\+\\~", " ", path)
    return(normalizePath(sub(needle, "", path)))
  } else {
    # 'source'd via R console
    return(normalizePath(sys.frames()[[1]]$ofile))
  }
}

Natürlich können Sie den else-Block immer noch wie aprstar erweitern.

iball
quelle
1

Wenn Sie anstelle des Skripts, foo.Rwenn Sie dessen Pfadposition kennen, Ihren Code so ändern können, dass er immer auf alle sourced-Pfade eines gemeinsamen Pfads verweist , rootkönnen diese eine große Hilfe sein:

Gegeben

  • /app/deeply/nested/foo.R
  • /app/other.R

Das wird funktionieren

#!/usr/bin/env Rscript
library(here)
source(here("other.R"))

Informationen zum Definieren von Projektwurzeln finden Sie unter https://rprojroot.r-lib.org/ .

mmell
quelle
Für mich macht das hier Paket genau den Job und scheint eine einfache Lösung zu sein
Ron
0
#!/usr/bin/env Rscript
print("Hello")

# sad workaround but works :(
programDir <- dirname(sys.frame(1)$ofile)
source(paste(programDir,"other.R",sep='/'))
source(paste(programDir,"other-than-other.R",sep='/'))
Kinjelom
quelle
Ich erhalte immer noch die Fehlermeldung "Fehler in sys.frame (1): nicht so viele Frames auf dem Stapel"
Michael Barton
0

Erstaunlich, dass es in R keine Struktur vom Typ '$ 0' gibt! Sie können dies mit einem system () -Aufruf eines in R geschriebenen Bash-Skripts tun:

write.table(c("readlink -e $0"), file="scriptpath.sh",col=F, row=F, quote=F)
thisscript <- system("sh scriptpath.sh", intern = TRUE)

Teilen Sie dann einfach den Namen scriptpath.sh für other.R auf

splitstr <- rev(strsplit(thisscript, "\\/")[[1]])
otherscript <- paste0(paste(rev(splitstr[2:length(splitstr)]),collapse="/"),"/other.R")
bruce.moran
quelle
Ich erhalte eine FehlermeldungreadLink: illegal option -- e usage: readLink [-FlLnqrsx] [-f format] [-t timefmt] [file ...]
altabq
0

Wenn wir uns den Aufrufstapel ansehen, können wir den Dateipfad jedes ausgeführten Skripts ermitteln. Die beiden nützlichsten sind wahrscheinlich entweder das aktuell ausgeführte Skript oder das erste Skript, das bezogen wird (Eintrag).

script.dir.executing = (function() return( if(length(sys.parents())==1) getwd() else dirname( Filter(is.character,lapply(rev(sys.frames()),function(x) x$ofile))[[1]] ) ))()

script.dir.entry = (function() return( if(length(sys.parents())==1) getwd() else dirname(sys.frame(1)$ofile) ))()
user425678
quelle