Funktion zum Verketten von Pfaden?

73

Gibt es eine Funktion zum Verketten von Pfaden?

Ich weiß, dass es nicht so schwierig zu implementieren ist, aber trotzdem ... abgesehen davon, dass ich mich um das Nachlaufen /(oder \) kümmere, müsste ich mich um die ordnungsgemäße Erkennung des Betriebssystempfadformats kümmern (dh ob wir schreiben C:\dir\fileoder /dir/file).

Wie gesagt, ich glaube zu wissen, wie man es umsetzt; Die Frage ist: soll ich es tun? Ist die Funktionalität bereits in einem vorhandenen R-Paket vorhanden?

Adam Ryczkowski
quelle

Antworten:

117

Ja, file.path()

R> file.path("usr", "local", "lib")
[1] "usr/local/lib"
R> 

Es gibt auch das gleichermaßen Nützliche system.path()für Dateien in einem Paket:

R> system.file("extdata", "date_time_zonespec.csv", package="RcppBDT")
[1] "/usr/local/lib/R/site-library/RcppBDT/extdata/date_time_zonespec.csv"
R> 

welches die Datei extdata/date_time_zonespec.csvunabhängig davon bekommt

  1. wo das Paket installiert ist, und
  2. das Betriebssystem

das ist sehr praktisch. Schließlich gibt es auch

R> .Platform$file.sep
[1] "/"
R> 

wenn Sie darauf bestehen, es manuell zu tun.

Dirk Eddelbuettel
quelle
3
Gute Antwort. Die Funktion kümmert sich jedoch nicht um das abschließende "/", was file.path("/home/user/","project")zu einer Ungültigkeit führt /home/user//project. Gibt es eine andere Funktion oder sollte ich sie selbst machen (allerdings trivial)?
Adam Ryczkowski
Sie erhalten es, wenn Sie mit einer leeren Zeichenfolge beginnen: file.path("", "home", "user", "project")Erzeugt"/home/user/project"
Dirk Eddelbuettel
4
Beachten Sie, dass /home/user//projectund /home/user/projectbeide unter Unix gültig sind. Auf welchem ​​Betriebssystem bist du?
Flodel
@flodel Er ... Linux. Aber ich wusste nichts davon. Vielen Dank! Und es scheint, dass es auch unter Windows (auf cmd.exe) gültig ist!
Adam Ryczkowski
Dies könnte grundlegendes R-Wissen sein, aber wenn Sie bereits Ihre Liste = Liste ("", "a", "b", "c") haben und diese in einen Pfad umwandeln möchten,do.call(file.path, yourlist)
Colin D
4

Falls jemand möchte, ist dies meine eigene Funktion path.cat. Seine Funktionalität ist vergleichbar mit der von Python os.path.joinmit dem zusätzlichen Zucker, den es interpretiert ...

Mit dieser Funktion können Sie Pfade hierarchisch erstellen, jedoch im Gegensatz zu file.path können Sie dem Benutzer die Möglichkeit geben, die Hierarchie zu überschreiben, indem Sie einen absoluten Pfad eingeben. Und als Zuckerzusatz kann er das ".." mit offensichtlicher Bedeutung in den Pfad setzen, wo immer er möchte.

z.B

  • path.cat("/home/user1","project/data","../data2") yelds /home/user1/project/data2

  • path.cat("/home/user1","project/data","/home/user2/data") yelds /home/user2/data

Die Funktion funktioniert nur mit Schrägstrichen als Pfadtrennzeichen, was in Ordnung ist, da R sie transparent in Backslashes auf Windows-Computern übersetzt.

library("iterators") # After writing this function I've learned, that iterators are very inefficient in R.
library("itertools")

#High-level function that inteligentely concatenates paths given in arguments
#The user interface is the same as for file.path, with the exception that it understands the path ".."
#and it can identify relative and absolute paths.
#Absolute paths starts comply with "^\/" or "^\d:\/" regexp.
#The concatenation starts from the last absolute path in arguments, or the first, if no absolute paths are given.
path.cat<-function(...)
{
  elems<-list(...)
  elems<-as.character(elems)
  elems<-elems[elems!='' && !is.null(elems)]
  relems<-rev(elems)
  starts<-grep('^[/\\]',relems)[1]
  if (!is.na(starts) && !is.null(starts))
  {
    relems<-relems[1:starts]
  }
  starts<-grep(':',relems,fixed=TRUE)
  if (length(starts)==0){
    starts=length(elems)-length(relems)+1
  }else{
    starts=length(elems)-starts[[1]]+1}
  elems<-elems[starts:length(elems)]
  path<-do.call(file.path,as.list(elems))
  elems<-strsplit(path,'[/\\]',FALSE)[[1]]
  it<-ihasNext(iter(elems))
  out<-rep(NA,length(elems))
  i<-1
  while(hasNext(it))
  {
    item<-nextElem(it)
    if(item=='..')
    {
      i<-i-1
    } else if (item=='' & i!=1) {
      #nothing
    } else   {
      out[i]<-item
      i<-i+1
    }
  }
  do.call(file.path,as.list(out[1:i-1]))
}
Adam Ryczkowski
quelle
1
Cooler Kommentar, aber es gibt einen wichtigen Unterschied: normalizePath()Der Pfad muss tatsächlich auf dem R-Server vorhanden sein. Dies ist möglicherweise nicht immer erwünscht. Für mich ist es ein wichtiger Unterschied. Laut OTOH-Handbuch werden normalizePath()kurze Namen unter Windows in lange konvertiert.
Adam Ryczkowski