2010-03-16 6 views
25

Estoy escribiendo un script de shell POSIX que puede o no recibir entrada de stdin (como en foo.sh < test.txt, de forma no interactiva). ¿Cómo compruebo si hay algo en stdin para evitar detenerme en while read -r line...?Detectar la presencia de contenido stdin en el script de shell

+0

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

Respuesta

39

Si consigo la pregunta correcta, puede intentar lo siguiente:

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

Solo un aviso, esto se activa para stdin y cuando se captura la salida estándar. (ambos se ejecutan interactivelly) ./yourscript <./the_input_your_giving_your_script.txt && ./yourscript> ./what_your_script_outputs.txt – DebugXYZ

+1

@DeShawnWilliams No, la respuesta de @dmedvinsky es correcta: 'test -tn' es verdadero si el descriptor de archivo' n' se abre en un terminal, por lo tanto 'test -t 0' solo busca stdin, y' test -t 1 'solo verifica el stdout. – bootleg

1

Si no desea ejecutar el script de forma interactiva, haga que tome el archivo de entrada como un parámetro, en lugar de usar stdin. Algunos programas usan una bandera o un nombre de archivo especial para indicar que deben tomar la entrada desde la entrada estándar en lugar de desde un archivo; ese caso te permite manejar maniobras de línea de comando si es necesario.

Si desea que su script tome la entrada estándar, ¿por qué no quiere que sea interactivo (o al menos se comporte como otras herramientas POSIX)?

+4

Una forma común de decirle a los programas que lean de stdin en su lugar de un archivo es proporcionar '-' en lugar de un nombre de archivo. – Cascabel

6

que se pueden implementar fácilmente un comportamiento similar al del comando "cat", que se lee de una lista de archivos proporcionados o si no se proporciona, luego lee del stdin.

Aunque usted no puede utilizar esta idea, creo que este artículo de Linux Journal será interesante para usted http://www.linuxjournal.com/content/determine-if-shell-input-coming-terminal-or-pipe

:-)

+0

Ummm, respuesta de d.m. es genial^_^ – darkturo

+0

Ese enlace fue muy útil, gracias! – hamstar

8

Para responder a la pregunta, literalmente, (pero no lo que realmente quiere): read -t 0

Tiempo de espera, cero segundos.

  1. esto es una condición de carrera, dependiendo de cuando el lado izquierdo está listo para proporcionar datos. Puede especificar -t 5 pero en un sistema de agolpamiento incluso eso es problemático.
  2. read -t no está estandarizado en SUSv3. Está en BSD sh, bash, zsh. No está en ksh o dash.

Así que no puedes usar #!/Bin/sh y esperar tener esto.

El problema básico es que incluso si no hay nada en stdin ahora, eso no significa que no habrá pronto. Invocar un programa normalmente deja stdin conectado a la terminal/lo que sea, por lo que no hay forma de saber qué se necesita.

lo tanto, para responder a su pregunta, literalmente, puede hacerlo, pero en la práctica sus opciones son:

  1. prueba si la entrada estándar es un tty: [ -t 0 ]
  2. uso argv para controlar el comportamiento
+1

Acabo de experimentar con esto usando zsh. Noté que 'read -t' o equivalente' read -t0' tienen un comportamiento ** no determinista **. Como ya lo mencionaste, evita usarlo. – Tarrasch

+1

Pero eso debe distinguirse del _test_ '-t' utilizado en la respuesta. –

Cuestiones relacionadas