Ottieni il percorso dello script corrente quando eseguito tramite un collegamento simbolico


59

Ho un'utilità composta da un paio di directory con alcuni script bash e file di supporto che verranno distribuiti su più macchine, possibilmente in una directory diversa su ogni macchina. Gli script devono poter fare riferimento ai percorsi relativi a se stessi, quindi devo essere in grado di ottenere il percorso del file attualmente in esecuzione.

Sono consapevole del dirname $0linguaggio che funziona perfettamente quando la mia sceneggiatura viene chiamata direttamente. Sfortunatamente c'è il desiderio di essere in grado di creare collegamenti simbolici a questi script da una directory totalmente diversa e avere ancora il relativo lavoro di logica di tracciamento.

Un esempio della struttura generale del dripping è il seguente:

/
 |-usr/local/lib
 |  |-foo
 |  |  |-bin
 |  |  |  |-script.sh
 |  |  |-res
 |  |  |  |-resource_file.txt
 |-home/mike/bin
 |  |-link_to_script (symlink to /usr/local/lib/foo/bin/script.sh)

Come posso fare riferimento in modo affidabile /usr/local/lib/foo/res/resource_file.txtdal script.shfatto che sia invocato da /usr/local/lib/foo/bin/script.sho ~mike/bin/link_to_script?

Risposte:


80

Prova questo come soluzione per scopi generici:

DIR="$(cd "$(dirname "$0")" && pwd)"

Nel caso specifico dei seguenti collegamenti simbolici, è possibile eseguire questa operazione:

DIR="$(dirname "$(readlink -f "$0")")"

Funziona perfettamente ed è molto più semplice delle cose che stavo provando. Grazie!
Mike Deck,

@MikeDeck Divertiti. Nota che ho risolto alcuni problemi di quotazione dal primo post ... potresti usare un'opzione dell'ultima modifica nel caso in cui tu abbia spazi o altri personaggi stravaganti nel tuo percorso qualche volta. Anche se non ha importanza per questo progetto, potresti copiare il codice dai tuoi script lungo la strada e avere l'opzione migliore conta allora!
Caleb,

1
Dovrei chiarire, il secondo funziona perfettamente. La prima soluzione che hai fornito non funziona per i collegamenti simbolici sul mio sistema.
Mike Deck,

4
@MikeDeck: la prima soluzione funziona nel caso tipico di avere varie directory collegate come link all'interno del percorso, ma non aiuterà se il binario finale è un link simbolico. Questo è ciò di cui il secondo riesce a prendersi cura.
Caleb,

1
Non funziona se il file di script è sourced (ad es. $ source ./sript.sh) Funziona in entrambi i casi:DIR="$(cd "$(dirname "$BASH_SOURCE")" && pwd)"
FractalSpace

7

una linea:

cd $(dirname $([ -L $0 ] && readlink -f $0 || echo $0))

2
Le risposte a una riga non sono in genere le più utili. Si prega di considerare di espandere la risposta per includere spiegazioni, collegamenti o documentazione che supportano ulteriormente la soluzione suggerita.
HalosGhost,

1
in realtà, non è necessario farlo, la versione readlink della risposta originale funziona bene se non è coinvolto alcun
collegamento


0

Una piccola aggiunta allo script sopra. L'opzione -P per pwd segue i symlink

DIR="$(cd "$(dirname "$0")" && pwd -P)"

7
Funziona solo quando il collegamento simbolico fa parte della struttura della directory. Non funziona quando il file stesso è collegato.
Oliver Gondža,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.