Как проверить, является ли stdin из терминала или канала в сценарии оболочки? - PullRequest
28 голосов
/ 16 марта 2010

Я пишу сценарий оболочки POSIX, который может или не может получать входные данные от стандартного ввода, как в foo.sh < test.txt, неинтерактивно.

Как проверить, есть ли что-нибудь на stdin, чтобы избежать остановки на while read -r line...?

Ответы [ 4 ]

44 голосов
/ 16 марта 2010

Если я правильно понял вопрос, вы можете попробовать следующее:

#!/bin/sh
if [ -t 0 ]; then
    echo running interactivelly
else
    while read -r line ; do
        echo $line
    done
fi
8 голосов
/ 16 марта 2010

Чтобы ответить на вопрос буквально (но не то, что вы на самом деле хотите): read -t 0

Тайм-аут, ноль секунд.

  1. это состояние гонки, в зависимости от того, когда левая сторона готова предоставить данные. Вы можете указать -t 5, но в системе с молотом даже это проблематично.
  2. read -t не стандартизировано в SUSv3. Это в БСД ш, баш, зш. Это не в кш или тире.

Так что вы не можете просто использовать #! / Bin / sh и ожидать получить это.

Основная проблема в том, что даже если на stdin сейчас ничего нет, это не значит, что скоро не будет. Вызов программы обычно оставляет подключенный stdin к терминалу / что угодно, поэтому нет способа определить, что нужно.

Итак, чтобы ответить на ваш вопрос буквально, вы можете это сделать, но на практике вы можете выбрать следующие варианты:

  1. проверка, является ли стандартное состояние tty: [ -t 0 ]
  2. использовать argv для управления поведением
6 голосов
/ 16 марта 2010

Вы можете легко реализовать поведение, аналогичное команде "cat", которая читается из списка предоставленных файлов или, если они не предоставлены, затем считывается из стандартного ввода.

Хотя вы не можете использовать эту идею, я думаю, что эта статья в Linux Journal будет вам интересна http://www.linuxjournal.com/content/determine-if-shell-input-coming-terminal-or-pipe

: -)

1 голос
/ 16 марта 2010

Если вы никогда не хотите запускать скрипт в интерактивном режиме, сделайте так, чтобы он принимал входной файл в качестве параметра, а не stdin. Некоторые программы используют флаг или специальное имя файла, чтобы указать, что они должны получать ввод из стандартного ввода, а не из файла; этот случай позволяет вам при необходимости обрабатывать командные строки.

Если вы хотите, чтобы ваш скрипт принимал стандартный ввод, почему вы не хотите, чтобы он был интерактивным (или, по крайней мере, вел себя как другие инструменты POSIX)?

...