2010-03-16 14 views
25

Sto scrivendo uno script di shell POSIX che può o non può ricevere input da stdin (come in foo.sh < test.txt, non in modo interattivo). Come posso verificare se c'è qualcosa su stdin, per evitare l'arresto su while read -r line...?Rileva presenza di contenuto di stdin nello script di shell

+0

stdout: http://stackoverflow.com/questions/911168/how-to-detect-if-my-shell-script-is-running- through-a-pipe –

risposta

39

Se avrò la giusta domanda, si può provare il seguente:

#!/bin/sh 
if [ -t 0 ]; then 
    echo running interactivelly 
else 
    while read -r line ; do 
     echo $line 
    done 
fi 
+0

Solo un avviso, questo viene attivato per lo stdin e quando si acquisisce lo stdout. (entrambi gestiscono interactivelly) ./yourscript <./the_input_your_giving_your_script.txt && ./yourscript> ./what_your_script_outputs.txt – DebugXYZ

+1

@DeShawnWilliams No, la risposta di @dmedvinsky è corretta: 'test -tn' è true se il descrittore di file' n' è aperto su un terminale, quindi 'test -t 0' controlla solo lo stdin e' test -t 1 'controlla solo lo stdout. – bootleg

1

Se non si desidera eseguire lo script in modo interattivo, farlo prendere il file di input come parametro anziché utilizzare stdin. Alcuni programmi usano un flag o un nome file speciale per indicare che dovrebbero prendere input da input standard piuttosto che da un file; quel caso ti permette di gestire il jockey a linea di comando se necessario.

Se si desidera che lo script prenda l'input standard, perché non si desidera che sia interattivo (o almeno si comporti come gli altri strumenti POSIX)?

+4

Un modo comune per dire ai programmi di leggere da stdin di un file è quello di fornire '-' invece di un nome di file. – Cascabel

6

si può facilmente implementare un comportamento simile a quello del comando "cat", che viene letto da un elenco di file forniti o se Non sono fornite, quindi leggere dallo stdin.

Anche se non è possibile utilizzare questa idea, credo che questo articolo Linux Journal sarà interessante per voi http://www.linuxjournal.com/content/determine-if-shell-input-coming-terminal-or-pipe

:-)

+0

Ummm, risposta da d.m. è cool^_^ – darkturo

+0

Questo link è stato molto utile, grazie! – hamstar

8

di rispondere alla domanda letteralmente (ma non quello che realmente vuole): read -t 0

Timeout, zero secondi.

  1. questa è una condizione di gara, a seconda di quando il lato sinistro è pronto a fornire i dati. È possibile specificare -t 5 ma su un sistema di thrashing anche questo è problematico.
  2. read -t non è standardizzato in SUSv3. È in BSD sh, bash, zsh. Non è in ksh o dash.

Quindi non si può semplicemente usare #!/Bin/sh e aspettarsi di avere questo.

Il problema di base è che anche se non c'è nulla su stdin ora, ciò non significa che non ci sarà presto. Invocare un programma normalmente lascia lo stdin connesso al terminale/qualunque cosa, quindi non c'è modo di dire cosa è necessario.

Quindi, per rispondere alla tua domanda, letteralmente, si può fare, ma in pratica le opzioni sono:

  1. test se stdin è un tty: [ -t 0 ]
  2. uso argv per controllare il comportamento
+1

Ho appena sperimentato questo usando zsh. Ho notato che 'read -t' o equivalentemente' read -t0' hanno un comportamento ** non deterministico **. Quindi, come hai già detto, evita di usarlo. – Tarrasch

+1

Ma, questo deve essere distinto dal _test_ '-t' usato nella risposta. –

Problemi correlati