Trova il percorso assoluto da uno script


10

In uno script ottengo $0il possibile percorso relativo ad esso. Per convertirlo in assoluto ho trovato questa soluzione che non capisco:

abspath=$(cd ${0%/*} && echo $PWD/${0##*/})

Il mio problema è la magia dentro ${0%/*}e ${0##*/}. Sembra che il primo estrae il dirname e il secondo estrae il nome del file, non capisco come.


2
Questo utilizza l'espansione dei parametri, ma non ha funzionato per me. Se lo script verrà utilizzato solo su Linux, è possibile utilizzare readlink -f $0per ottenere il percorso canonico.
Shawn J. Goff,

1
@Shawn: 1 voto di commento eccezionale perché hai introdotto il pensiero giusto: "Questo utilizza l'espansione dei parametri, ma non ha funzionato per me". L' dirnameutilità è utile qui.
D4RIO,

mywiki.wooledge.org/BashFAQ/028 e cyberciti.biz/faq/… dice che BASH_SOURCEè meglio di $0, dato che $0dà il comando digitato dall'utente, che potrebbe non essere lo script attualmente in esecuzione.
Joel Purra,

Risposte:


8

definizioni:

${string%substring} cancella la partita più breve di $substringdalla fine di $string.

${string##substring}cancella la partita più lunga $substringdall'inizio $string.

Il tuo esempio:

abspath=$(cd ${0%/*} && echo $PWD/${0##*/})

${0%/*} elimina tutto dopo l'ultima barra, dandoti il ​​nome della directory dello script (che potrebbe essere un percorso relativo).

${0##*/} elimina tutto fino all'ultima barra, dandoti solo il nome dello script.

Quindi, questo comando cambia nella directory dello script e concatena la directory di lavoro corrente (data da $PWD) e il nome dello script fornendo il percorso assoluto.

Per vedere cosa sta succedendo, prova:

echo ${0%/*}
echo ${0##*/}

Aggiungi virgolette doppie intorno a tutte le espansioni variabili per far fronte a (quasi tutti) nomi di file contenenti caratteri speciali della shell.
Gilles 'SO- smetti di essere malvagio' il

10

Shawn ha avuto la soluzione più semplice: readlink -f $0. Se vuoi essere assolutamente sicuro di gestire nomi di file strani, puoi usare questo:

absolute_path_x="$(readlink -fn -- "$0"; echo x)"
absolute_path="${absolute_path_x%x}"

Documentazione


1
Bello vedere le newline finali gestite correttamente. Sfortunatamente readlink -fnè specifico per Linux, NetBSD e OpenBSD.
Gilles 'SO- smetti di essere cattivo'

4

Ecco un modo più sicuro e più leggibile per fare questo lavoro:

abspath=$(unset CDPATH && cd "$(dirname "$0")" && echo $PWD/$(basename "$0"))

Appunti:

  • Se $0è un nome file nudo senza percorso precedente, lo script originale non funzionerà, ma quello indicato qui funzionerà. (Non è un problema con $0ma potrebbe essere in altre applicazioni.)
  • Entrambi gli approcci falliranno se il percorso del file non esiste realmente. (Non è un problema $0, ma potrebbe essere in altre applicazioni.)
  • Il unsetè essenziale se l'utente può aver CDPATHimpostato.
  • A differenza di readlink -fo realpath, questo funzionerà su versioni non Linux di Unix (ad esempio, Mac OS X).

2

Se vuoi imparare Shell Parameter Expansion, puoi leggerlo da qui , ma Expansion non è sempre una buona scelta. In questo caso, quasi ogni sistema simile a Unix ha 2 buoni programmi di utilità:

basename
dirname

Il primo estrarrà il nome del file, mentre il secondo estrarrà il percorso, quindi, se hai $ 0, di ':

dirname $0

E otterrai il percorso.

Saluti


dirname può restituire percorsi relativi
ottico

0

Presentazione di pwd, il bash incorporato. Si trova anche nel pacchetto GNU coreutils.

$ sh ./cygdrive/c/cygwin/home/../../../../home/jaroslav/tmp/somewhere.sh
$0: ./cygdrive/c/cygwin/home/../../../../home/jaroslav/tmp/somewhere.sh
cheeky binary from /home/jaroslav/tmp (/home/jaroslav/tmp)

$ cat /home/jaroslav/tmp/somewhere.sh

abs=$( cd `dirname "$0"` ; pwd -P)
absBin=$( cd `dirname "$0"` ; /bin/pwd -P)
echo \$0: $0
echo cheeky binary from $abs \($absBin\)
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.