2011-09-28 15 views
6

mi piacerebbe girare il seguente:processo Bash di sostituzione e di uscita codici

git status --short && (git status --short | xargs -Istr test -z str)

che mi ottiene il risultato desiderato di mirroring l'output a stdout e facendo un controllo di lunghezza zero sul risultato in qualcosa più vicina a:

git status --short | tee >(xargs -Istr test -z str)

che restituisce purtroppo il codice di uscita del T (sempre zero).

C'è un modo per ottenere elegantemente il codice di uscita del processo sostituito?

[EDIT]

sto andando con la seguente, per ora, impedisce l'esecuzione lo stesso comando due volte, ma sembra a mendicare per qualcosa di meglio:

OUT=$(git status --short) && echo "${OUT}" && test -z "${OUT}"

+0

Scusami, ma cosa vuoi raggiungere esattamente? Basta controllare se c'è stato git in quella directory? –

+0

Sì, fa parte di uno script di distribuzione e dovrebbe uscire diverso da zero se la directory è sporca. – jodell

risposta

5

Guardate qui:

 
    $ echo xxx | tee >(xargs test -n); echo $? 
xxx 
0 
    $ echo xxx | tee >(xargs test -z); echo $? 
xxx 
0 

e potete trovare qui:

 
    $echo xxx | tee >(xargs test -z; echo "${PIPESTATUS[*]}") 
xxx 
123 
    $echo xxx | tee >(xargs test -n; echo "${PIPESTATUS[*]}") 
xxx 
0 

Cioè?

Vedi anche Pipe status after command substitution

+0

Non sapevo di PIPESTATUS, è stato utile, grazie. – jodell

+4

Nel caso che qualcun altro arrivi e pensa che PIPESTATUS risolva questo problema, non lo fa. Se l'eco $? viene spostato all'interno del costrutto> (...), inoltre si comporta come previsto. Se la versione di PIPESTATUS viene spostata all'esterno, restituisce anche 0 in entrambi i casi. –

0
#!/bin/bash 
if read q < <(git status -s) 
then 
    echo $q 
    exit 
fi 
2

Ho lavorato su questo per un po ', e sembra che non c'è modo di farlo con sostituzione di processo, ad eccezione di ricorrere a inline di segnalazione, e che può essere usato solo per le pipe di input, quindi non lo espanderò.

Tuttavia, bash-4.0 fornisce coprocessi che possono essere utilizzati per sostituire la sostituzione di processo in questo contesto e fornire un raccolto pulito.

il seguente frammento fornito da voi:

git status --short | tee >(xargs -Istr test -z str) 

può essere sostituito da qualcosa di simile:

coproc GIT_XARGS { xargs -Istr test -z str; } 
{ git status --short | tee; } >&${GIT_XARGS[1]} 
exec {GIT_XARGS[1]}>&- 
wait ${GIT_XARGS_PID} 

Ora, per qualche spiegazione:

La chiamata coproc crea un nuovo coprocesso, nominandolo GIT_XARGS (puoi usare qualsiasi nome tu voglia), ed eseguendo il comando tra parentesi. Viene creata una coppia di pipe per la coprocessione, reindirizzando lo stdin e lo stdout.

La chiamata coproc imposta due variabili:

  1. ${GIT_XARGS[@]} contenente tubi per elaborare stdin e stdout, opportunamente ([0] per leggere da stdout, [1] scrivere a stdin),
  2. ${GIT_XARGS_PID} contenenti il ​​coprocesso PID.

Successivamente, il comando viene eseguito e la sua uscita è diretto verso il secondo condotto (cioè coprocesso stdin). La parte >&${GIT_XARGS[1]} che appare in modo criptico viene espansa a qualcosa come >&60 che è il normale reindirizzamento da output a dia.

Si prega di notare che avevo bisogno di mettere il comando in parentesi graffe. Questo perché una pipeline genera i sottoprocessi e non eredita i descrittori di file dal processo padre. In altre parole, il seguente:

git status --short | tee >&${GIT_XARGS[1]} 

avrebbero esito negativo con l'errore non valida descrittore di file, dal momento che il fd rilevante esiste nel processo genitore e non il generato tee processo. Inserendolo in coppia, bash applica il reindirizzamento all'intera pipeline.

La chiamata exec viene utilizzata per chiudere il tubo al coprocessore. Quando hai utilizzato la sostituzione di processo, il processo è stato generato come parte del reindirizzamento dell'output e la pipe ad esso è stata chiusa immediatamente dopo che il reindirizzamento non ha avuto più effetto. Dal momento che la durata del coprocess 'pipe si estende oltre un singolo reindirizzamento, è necessario chiuderla in modo esplicito.

La chiusura del tubo di uscita dovrebbe causare il processo per ottenere la condizione EOF su stdin e terminare correttamente. Usiamo wait per attendere la sua conclusione e raccoglierla. wait restituisce lo stato di uscita della coprocessa.

Come nota finale, si noti che in questo caso non è possibile utilizzare kill per interrompere la coprocessione poiché ciò ne modifica il suo stato di uscita.

+0

in questo caso non è più utile, la rete stdout reindirizza allo stdout. – weynhamz

+0

'exec {GIT_XARGS [1]}> & -' restituisce '-bash: exec: {GIT_XARGS [1]}: non trovato' per me. –

+0

Hai bash-4.0 o più recente? –

Problemi correlati