Dal manuale di Bash ( man bash):
Sostituzione comando
La sostituzione di comando consente all'output di un comando di sostituire il
nome del comando. Esistono due forme:
$ (Comando)
o
`comando`
Bash esegue l'espansione eseguendo il comando in una subshell
ambiente e sostituzione della sostituzione dei comandi con lo standard
output del comando, con eventuali newline finali cancellate. Incorporato
le nuove righe non vengono eliminate, ma possono essere rimosse durante le parole
splitting. La sostituzione del comando $ (file cat) può essere sostituita da
$ (<file) equivalente ma più veloce.
(Questo vale per tutti i Bourne-come conchiglie, vale a dire sh, ksh, zsh, bashecc, ed zshè anche in grado di acquisire dati con caratteri NUL incorporati in questo modo)
Il comando
basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
assegnerà il nome della directory in cui si trova lo script (modificando anche tutte le barre rovesciate in barre) alla variabile basedir. Eventuali errori, avvisi o altri messaggi diagnostici inviati allo stream di errore standard verranno comunque visualizzati sul terminale ( $(...)acquisisce solo l'output standard del comando).
La shell inizierà eseguendo la sostituzione del comando più interna:
echo "$0" | sed -e 's,\\,/,g'
L'output di quello verrà dato come una stringa a dirname, e l'output di quello verrà assegnato alla variabile basedir.
Le doppie virgolette sono lì per assicurarsi che non venga eseguita alcuna suddivisione di parole o globbing del nome file, altrimenti potresti scoprire che lo script non riesce o produrre strani output quando $0(il nome dello script incluso il percorso utilizzato per eseguirlo) contiene uno spazio carattere o un carattere globbing del nome file (come ?o *).
È generalmente una buona idea citare sempre espansioni (espansioni variabili, sostituzioni di comandi ed espansioni aritmetiche). Vedi questa domanda e le sue risposte per un'eccellente spiegazione del perché questa è una buona idea.
Se lo script è stato eseguito come
$ /usr/local/bin/script.sh
quindi basedirotterrà il valore di /usr/local/bin.
Oppure, su Cygwin:
$ bash c:\\Users\\Me\\script.sh
quindi basedirotterrà il valore di c:/Users/Me. Le doppie barre rovesciate sulla riga di comando in questo caso servono solo a sfuggire alle singole barre rovesciate dalla shell. Il valore reale di $0è c:\Users\Me\script.sh.
Un altro modo di fare la stessa cosa senza usare dirname, echoe sedsarebbe
basedir="${0//\\//}"
basedir="${basedir%/*}"
man bashe cerca la sostituzione di comando