ksh: как зондировать stdin? - PullRequest
4 голосов
/ 11 марта 2009

Я хочу, чтобы мой сценарий ksh вел себя по-разному в зависимости от того, поступает ли что-то через stdin или нет:

    (1) cat file.txt | ./script.ksh  (then do "cat <&0 >./tmp.dat" and process tmp.dat)
vs. (2) ./script.ksh (then process $1 which must be a readable regular file)

Проверка stdin на наличие терминала [-t 0] не помогает, потому что мой скрипт вызывается из другого скрипта.

Выполнение команды "cat <& 0> ./ tmp.dat" для проверки размера файла tmp.dat в ожидании EOF от stdin, если stdin "пуст" (2-й случай).

Как просто проверить, является ли stdin "пустым" или нет? *

Ответы [ 3 ]

3 голосов
/ 11 марта 2009

РЕДАКТИРОВАТЬ: вы работаете на HP-UX

Протестировано [ -t 0 ] на HP-UX, и, похоже, оно работает для меня. Я использовал следующую настройку:

/tmp/x.ksh:

#!/bin/ksh
/tmp/y.ksh

/tmp/y.ksh:

#!/bin/ksh
test -t 0 && echo "terminal!"

Бег /tmp/x.ksh печатает: terminal!

Не могли бы вы подтвердить вышеизложенное на вашей платформе и / или предоставить альтернативную настройку теста, более точно отражающую вашу ситуацию? Ваш сценарий в конечном итоге порожден cron?


РЕДАКТИРОВАТЬ 2

Если отчаянно и Perl доступен, определите:

stdin_ready() {
  TIMEOUT=$1; shift
  perl -e '
    my $rin = "";
    vec($rin,fileno(STDIN),1) = 1;
    select($rout=$rin, undef, undef, '$TIMEOUT') < 1 && exit 1;
  '
}

stdin_ready 1 || 'stdin not ready in 1 second, assuming terminal'

РЕДАКТИРОВАТЬ 3

Обратите внимание, что время ожидания может быть значительным, если ваш ввод поступает из sort, ssh и т. Д. (Все эти программы могут порождать и устанавливать канал с вашим скриптом за секунды или минуты, прежде чем производить какие-либо данные поверх него. ) Кроме того, использование значительного тайм-аута может значительно наказать ваш сценарий, когда на входе нет ничего для начала (например, терминал.)

Если потенциально большие тайм-ауты являются проблемой, и если вы можете повлиять на способ вызова вашего скрипта, то вы можете заставить вызывающих абонентов явно указывать вашей программе, следует ли использовать stdin, через пользовательский параметр или в стандартным способом GNU или tar (например, script [options [-]] FILE ..., где FILE может быть именем файла, - для обозначения стандартного ввода или их комбинации, и ваш скрипт будет читать только из стандартного ввода, если - передано в качестве параметра.)

2 голосов
/ 03 апреля 2009

Эта стратегия работает для bash и, вероятно, будет работать для ksh. Опрос 'tty':

#!/bin/bash
set -a

if [ "$( tty )" == 'not a tty' ]
then
    STDIN_DATA_PRESENT=1
else
    STDIN_DATA_PRESENT=0
fi

if [ ${STDIN_DATA_PRESENT} -eq 1 ]
then
    echo "Input was found."
else
    echo "Input was not found."
fi
0 голосов
/ 26 марта 2009

Почему бы не решить эту проблему более традиционным способом и использовать аргумент командной строки, чтобы указать, что данные будут поступать из стандартного ввода?

Для примера рассмотрим разницу между:

echo foo | cat -

и

echo foo > /tmp/test.txt

cat /tmp/test.txt

...