2012-10-28 19 views
43

Esiste una funzione esistente per concatenare i percorsi?Funzione per concatenare percorsi?

So che non è poi così difficile da implementare, ma ancora ... oltre a prendersi cura di ultimi / (o \) avrei bisogno di prendersi cura di rilevamento formato percorso corretto OS (vale a dire se scriviamo C:\dir\file o /dir/file) .

Come ho detto, credo di sapere come implementarlo; la domanda è: dovrei farlo? La funzionalità esiste già nel pacchetto R esistente?

risposta

74

Sì, file.path()

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

C'è anche l'altrettanto utile system.path() per i file in un pacchetto:

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

che otterrà il file extdata/date_time_zonespec.csv indipendentemente

  1. dove la il pacchetto è installato e
  2. l'OS

che è molto utile. Infine, c'è anche

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

se insistete a farlo manualmente.

+1

Ottima risposta. Ma la funzione non si occupa del trailing "/", quindi 'file.path ("/home/user/"," project ")' produce un progetto '/ home/utente // non valido '. C'è un'altra funzione, o dovrei farlo da solo (banalmente, però)? –

+0

Si ottiene se si inizia con una stringa vuota: 'file.path (" "," home "," utente "," progetto ")' produce '"/home/utente/progetto "' –

+2

Si noti che '/ home/utente // project' e '/ home/user/project' sono entrambi validi su Unix. Su quale sistema operativo sei? – flodel

2

Se qualcuno lo desidera, questa è la mia funzione path.cat. La sua funzionalità è paragonabile a quella di Python os.path.join con lo zucchero extra, che interpreta lo ...

Con questa funzione, è possibile costruire i percorsi gerarchicamente, ma a differenza dello file.path, si lascia all'utente la possibilità di sovrascrivere la gerarchia impostando un percorso assoluto. E come aggiunta di zucchero, può mettere il ".." ovunque nel percorso, con ovvio significato.

ad es.

  • 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

La funzione funziona solo con barre come separatore di percorso, che va bene, poiché R li traduce trasparente a barre rovesciate sulla macchina Windows.

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])) 
} 
+1

Questo è fatto da normalizePath() –

+1

Un commento interessante, ma c'è una differenza importante:' normalizePath() 'richiede che il percorso sia effettivamente presente sul server R. Questo potrebbe non essere sempre desiderato. Per me è una differenza importante. Il manuale di OTOH dice 'normalizePath()' converte i nomi brevi in ​​long su Windows. –

Problemi correlati