2009-03-11 4 views
4

Я хочу, чтобы мой сценарий КШ иметь различное поведение в зависимости от того, есть что-то входящий через стандартный ввод или нет: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) 

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

Doing "кошачий < & 0> ./ tmp.dat", чтобы проверить размер tmp.dat висит вверх ждет EOF из стандартного ввода, если STDIN "пустой" (второй случай).

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

+0

как насчет проверки длины аргументов? ($ #), если есть $ 1, то вы завершаете чтение. если нет, читайте из stdin, я бы сказал. –

+0

Если бы я только мог! использование: ./script.ksh <-d dest> [-f from_sys] [файл, файл1, ..]. Если stdin => [file, file1, ..] не обрабатывается, просто перемещается. Если нет файла stdin => process, переместите файл1, .. Если нет ошибки stdin, а также [file, file1, ..] =>: пользователь должен предоставить некоторые для обработки! – 2009-03-11 16:58:19

+0

ExpertNoob, вы можете пометить этот вопрос как ответ. :) – vladr

ответ

3

EDIT: Вы работаете на 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?


EDIT 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' 

EDIT 3

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

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

+0

Я нахожусь на HP-UX :-( Есть ли среднее отображение существующих труб под HP-UX? – 2009-03-11 19:26:34

+0

Хммм, но 'test -t 0' правильно идентифицирует fd как терминал на моем hpux, даже если тест выполняется из скрипта, называемого другим скриптом (HP-UX HP-A500 B.11.11 U 9000/800 538790518 безлимитный пользователь) – vladr

+0

Ну, test -t 0 тоже работает в моих тестах, но мой скрипт называется десятками других, некоторые из них должны делать черную магию с файловыми дескрипторами .. Мой скрипт должен заменить существующий на многих серверах по всему миру, поэтому он должен быть пуленепробивным. Ваше решение perl отлично, я тестирую его сейчас. Спасибо! – 2009-03-12 09:28:51

0

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

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

echo foo | cat -

и

echo foo > /tmp/test.txt

cat /tmp/test.txt

2

Эта стратегия работает на баш, и, скорее всего, работать на 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

Также работает с ksh. – Boune

+2

Пожалуйста, не забывайте, что в неанглийских системах вы получите локализованную версию «not tty». Одна из возможностей избежать этого - добавить строку «LANG = C» в верхней части скрипта. – chiborg

Смежные вопросы