Newsgroup: it.comp.lang.perl
Titolo: Ottenere il full path di un file

Approfitto di nuovo della vostra esperienza :) per chiedere: come
ottengo il percorso completo di un file aperto? Si puo' ottenere dal
descrittore del file?
Il mio problema e' che come parametri dello script mi vengono passati
alcuni nomi di file, spesso con percorsi relativi, e per debug vorrei
stampare a schermo i percorsi assoluti. Immagino ci sia un comando per
farlo, ma google non mi e' stato d'aiuto :(
Thx,
Pleg

 farlo, ma google non mi e' stato d'aiuto :(
Se hai i percorsi relativi, la cosa pi� semplice � usare il metodo 
rel2abs() di File::Spec
http://search.cpan.org/~smueller/PathTools-3.30/lib/File/Spec.pm
Esempio:
$ perl -MFile::Spec -e 'print File::Spec->rel2abs( ".bashrc" )'
/home/emanuele/.bashrc
(attenzione per� che non controlla che il file esista veramente nel 
filesystem, devi farlo tu, ad esempio aprendo prima il file).

 filesystem, devi farlo tu, ad esempio aprendo prima il file).
Se vuoi anche questo controllo, puoi usare realpath() di Cwd:
$ perl -MCwd=realpath -e 'print realpath( ".bashrc" ), "\n"'
/home/Emanuele/.bashrc
$ perl -MCwd=realpath -e 'print realpath( ".bashr" ), "\n"'
.bashr: No such file or directory at -e line 1
che fa proprio il traversing del filesystem (pertanto � per� pi� lento).
Ciao!

Pleg wrote:

Attenzione che il problema di determinare il full path partendo dal path
relativo e' tutt'altro che semplice, e in alcuni casi impossibile (o
perlomeno non univocamente).
Per cui spero che le soluzioni consigliate da Emanuele siano sufficienti per
la tua situazione.

antani wrote:

A cosa ti riferisci?
Nel suo caso mi sembra ovvio che i path siano relativi alla cwd.

> Nel suo caso mi sembra ovvio che i path siano relativi alla cwd.
E' corretto, sono tutti relativi alla cwd.
E grazie ancora!
Pleg

 Nel suo caso mi sembra ovvio che i path siano relativi alla cwd.
Premesso che e' tutto accademico, anche considerando che le tue soluzioni
sono state sufficienti...comunque (scusandomi per l'OT):
si', relativi alla cwd, ma qual e' la cwd?
Esempio banale:
$ pwd
/
$ ls -ld
drwxr-xr-x 2 root root 4096 2009-07-22 20:25 dir1
lrwxrwxrwx 1 root root    4 2009-07-22 20:25 dir2 -> dir1
$ cd dir1
$ pwd
/dir1
$ cd ..
$ cd dir2
$ pwd
/dir2
Quindi se dir1 contiene il file "file1", e io faccio
$ 
trovafullpath.pl
 file1
dopo esserci entrato con "cd /dir1", mi aspetto che il full path venga
risolto in /dir1/file1, ma se ci sono entrato da dir2 magari mi aspetterei
che mi desse /dir2/file1. Il problema e' che lo script non necessariamente
conosce o e' in grado di scoprire tale informazione, e deve
quindi "chiedere" al sistema operativo o a qualche altra entita'
superiore :)
Ma l'idea di "current working directory" non e' univoca; la shell ne ha una
(vedi sopra e nel prossimo esempio), il sistema operativo ne ha un'altra:
$ pwd
/
$ cd dir1
$ ls -l /proc/self/cwd
lrwxrwxrwx 1 root root 0 2009-07-22 23:34 /proc/self/cwd -> /dir1
$ pwd
/dir1
$ cd ..
$ cd dir2
$ ls -l /proc/self/cwd
lrwxrwxrwx 1 root root 0 2009-07-22 23:34 /proc/self/cwd -> /dir1  # oh-oh!
$ pwd
/dir2
Per approfondimento, questo paper descrive bene il problema:
http://plan9.bell-labs.com/sys/doc/lexnames.html
nella prima parte, prima di entrare nello specifico di plan9, c'e'
un'analisi delle problematiche introdotte dai link nei filesystem.
Fine dell'OT :)

 perlomeno non univocamente).
dalla quale m'era sembrato (magari erroneamente) che reputassi 
impossibile ottenere (nel caso generale), a partire da un path relativo 
utilizzato in uno script Perl, un path assoluto che puntasse allo stesso 
file.
Se invece ti riferivi al fatto che nel filesystem ci possono essere pi� 
path che puntano allo stesso file, siamo d'accordo ;-)
Ciao.

 path che puntano allo stesso file, siamo d'accordo ;-)
Bene :)
Ciao!

 l' "accuratezza", per cosi' dire, di tale path.
OK, ï¿œ un'osservazione che trovo condivisibile e pertinente.
Tanto da postare il codice per ottenere il full path come visto dalla 
shell ( oltre a quello giï¿œ postato in precedenza che fa uso di getcwd(3) ):
$ perl -MFile::Spec -e 'print File::Spec->rel2abs("rel/path/to/file", 
$ENV{PWD})'
questo nel tuo caso darebbe: /abc/def/ghi/jkl/mno/rel/path/to/file
(sempre in maniera portabile su diversi SO).
Quindi ora abbiamo sia il full path visto da getcwd(3) che quello visto 
dalla shell.
Direi che sono coperte tutte le esigenze che l'utente possa avere, e non 
ï¿œ stato cosï¿œ complicato ;-)
Ciao!

 $ENV{PWD})'
Per completezza, una nota su $ENV{PWD}
Se l'applicazione invocasse il builtin chdir(), $ENV{PWD} non verrebbe 
aggiornata.
Per ovviare a questo problema, basta:
use Cwd qw(chdir);
che sovrascrive il builtin chdir() con una propria versione che invece 
mantiene $ENV{PWD} aggiornata.

 è stato così complicato ;-)
Vedi sopra :)
Ciao!

 preferirebbe la semantica X anziche' la semantica Y per tali parti.
Se ti riferisci al fatto che non si sa se l'utente preferisca il path 
canonico verso un file, oppure uno degli N link allo stesso file 
eventualmente disponibili, posso essere d'accordo, ma non mi sembra 
rilevante.
Se invece intendevi che non si sa in quale modo l'utente voglia 
risolvere ".." e ".", giï¿œ non sono piï¿œ d'accordo, perchï¿œ l'unica 
soluzione generale possibile e quella del path canonico, come abbiamo visto.
Ciao!

 visto.
Ah certo, "." e ".." essendo hard link (sempre escludendo la possibilita'
per l'utente di creare hard link a directory) possono essere risolti solo
in un modo, che e' quello che usa realpath(3). 
Quello che dicevo e' che cosi' facendo si potrebbero perdere informazioni,
in quanto in una direzione (verso il "basso") si possono avere n nomi o
link per la stessa risorsa (directory in questo caso), mentre nell'altra
direzione (verso "l'alto") il rapporto e' 1:1 per il modo, appunto, in
cui "." e ".." DEVONO essere interpretati.
Comunque non voglio fare troppo l'avvocato del diavolo, anche perche' la
discussione e' gia' durata anche troppo: sono d'accordo che in certe
situazioni (che possono diventare anche tutte, a seconda delle circostanze)
usare il path di realpath(3) e' l'unica possibilita' per eliminare le
ambiguita'.