Prendiamo le due righe sottostanti che ci danno due risultati diversi.
p=$(cd ~ && pwd) ; echo $p
p=$(cd ~ | pwd) ; echo $p
In cosa differiscono i due?
|corsa vengono eseguiti in subshells.
Prendiamo le due righe sottostanti che ci danno due risultati diversi.
p=$(cd ~ && pwd) ; echo $p
p=$(cd ~ | pwd) ; echo $p
In cosa differiscono i due?
|corsa vengono eseguiti in subshells.
Risposte:
In p=$(cd ~ && pwd):
La sostituzione del comando, $()viene eseguita in una subshell
cd ~cambia directory in ~(la tua home), se cdriesce ( &&) quindi pwdstampa il nome della directory su STDOUT, quindi la stringa salvata su psarà la tua home directory ad es./home/foobar
In p=$(cd ~ | pwd):
Di nuovo $()genera una subshell
I comandi su entrambi i lati della |corsa vengono eseguiti nei rispettivi sottotitoli (ed entrambi iniziano contemporaneamente)
così cd ~viene fatto in una subshell e pwdin una subshell separata
quindi otterresti solo lo STDOUT, pwdovvero da dove esegui il comando, questa può essere qualsiasi directory come puoi immaginare, quindi pconterrà il nome della directory da cui viene invocato il comando, non la tua home directory
cd ~non produce alcun output e pwdnon legge alcun input.
(cd ~);p=$(pwd)non è vero?
Il problema principale è come gli operatori &&e |collegano i due comandi.
Il &&collega i comandi tramite il codice di uscita. Il |collega i due comandi tramite i descrittori di file (stdin, stdout).
Semplifichiamo prima. Possiamo rimuovere l'incarico e scrivere:
echo $(cd ~ && pwd)
echo $(cd ~ | pwd)
Possiamo anche rimuovere la sotto-shell di esecuzione del comando per analizzare questo:
$ cd ~ && pwd
$ cd ~ | pwd
Se cambiamo il prompt per mostrare la directory in cui vengono eseguiti i comandi, qualcosa del genere PS1='\w\$ ', vedremo questo:
/tmp/user$ cd ~ && pwd
/home/user
~$
cd ~cambiato la "directory presente" nella home dell'utente reale che sta eseguendo il comando ( /home/user).pwdper ~come è dimostrato dalla tempestivo ~$.Se la modifica della directory non ha avuto esito positivo (codice di uscita diverso da 0) per qualche motivo (la directory non esiste, il blocco delle autorizzazioni legge la directory) il comando successivo non verrà eseguito.
Esempio:
/tmp/user$ false && pwd
/tmp/user$ _
Il codice di uscita 1 da falseimpedisce l'esecuzione del comando successivo.
Pertanto, il codice di uscita di "comando 1" è ciò che influenza il "comando 2".
Ora, gli effetti dell'intero comando:
/tmp/user$ echo $(cd ~ && pwd)
/home/user
/tmp/user$ _
La directory è stata modificata, ma all'interno di una sotto-shell $(…), la directory modificata viene stampata /home/user, ma viene immediatamente scartata quando la sotto-shell si chiude. Il pwd ritorna ad essere la directory iniziale ( /tmp/user).
Questo è ciò che succede:
/tmp/user$ cd ~ | pwd
/tmp/user
/tmp/user$ _
Il meta-carattere |(non un vero operatore) segnala alla shell di creare ciò che viene chiamato "Pipe", (in bash) ogni comando su ciascun lato della pipe ( |) è impostato all'interno di ogni sub-shell, prima il lato destro comando, quindi, quello di sinistra. Il descrittore di file di input ( /dev/stdin) del comando destro è collegato al descrittore di output ( /dev/stdout) e quindi entrambi i comandi vengono avviati e lasciati interagire. Il comando left ( cd -) non ha output e, inoltre, il comando right ( pwd) non accetta input. Quindi, ognuno funziona in modo indipendente all'interno di ogni sub-shell.
cd ~cambia la pwd di una conchiglia.pwdstampa il pwd (completamente indipendente) dell'altra sub-shell.Le modifiche su ogni shell vengono scartate quando termina la pipe, la sub-shell esterna non ha modificato la pwd.
Ecco perché i due comandi sono collegati solo da "descrittori di file".
In questo caso, non viene inviato nulla e non viene letto nulla.
L'intero comando:
$ echo "$(cd ~ | pwd)"
Stampa solo la directory in cui è stato eseguito il comando.
Non sono sicuro se intendevi "|" o '||' nel tuo secondo caso.
'|' in una shell convoglia l'output di un comando all'input di un altro - un caso d'uso comune è qualcosa di simile: ad
curl http://abcd.com/efgh | grep ijkl
esempio eseguire un comando e utilizzare un altro comando per elaborare l'output di un comando.
Nell'esempio fornito, è abbastanza privo di senso, in quanto "cd" in genere non genera alcun output e "pwd" non prevede alcun input.
"&&" e "||" sono comandi del partner però. Sono progettati per essere utilizzati allo stesso modo degli operatori logici "e" e "o" nella maggior parte delle lingue. Tuttavia, le ottimizzazioni che vengono eseguite danno loro un comportamento specifico che è un paradigma di programmazione della shell.
Per determinare il risultato di un'operazione "e" logica, è necessario valutare la seconda condizione solo se la prima condizione ha esito positivo - se la prima condizione ha esito negativo, il risultato complessivo sarà sempre falso.
Per determinare il risultato di un'operazione "o" logica, è necessario valutare la seconda condizione solo se la prima condizione ha esito negativo - se la prima condizione ha esito positivo, il risultato complessivo sarà sempre vero.
Quindi, nella shell, se lo si command1 && command2 command2sarà eseguito solo quando command1è stato completato e restituito un codice risultato positivo. Se hai command1 || command2 command2eseguito verrà eseguito al command1termine se command1restituisce un codice di errore.
Un altro paradigma comune è quello di avere command1un comando test - questo genera una singola riga if / then statement - per esempio:
[ "$VAR" = "" ] && VAR="Value if empty"
È un modo (lungo) di assegnare un valore a una variabile se è attualmente vuota.
Esistono molti esempi dell'uso di questo processo altrove su Stack Exchange