Использование файла ввода в качестве стандартного ввода для сценария оболочки не работает

996
Mohamed KALLEL

У меня есть следующий код скрипта:

test.sh

echo "BEGIN" while read CMD <&1; do [ -z "$CMD" ] && continue case "$CMD" in start) echo "get_start" ;; stop) echo "get_stop" ;; *) echo "get_uknown_command" ;; esac echo "END"; done 

Когда я запускаю его с:

$./test.sh <input.txt 

Я заблокировал свой сценарий

input.txt

start stop sthh 

Почему мой скрипт заблокирован? Как я могу это исправить?

Кстати: если я введу данные вручную, сценарий не будет заблокирован.

0

2 ответа на вопрос

3
John Szakmeister

You're using the wrong file descriptor. 1 is stdout, 0 is stdin.

Change:

while read CMD <&1; do 

to:

while read CMD <&0; do 

And it will from the file correctly. However, you don't need to do that all since read defaults to using stdin:

while read CMD; do 

Also, the -u option can be used to read from a particular file descriptor (at least in bash). So you could do this as well:

while read -u 0 CMD; do 
2
a CVn

File descriptor 1 is stdout or standard output. Which means that you are redirecting read's input to come from standard output. This clearly isn't going to work very well; there will almost certainly never be any input waiting on the standard output for read.

Standard input is file descriptor 0, so if you change <&1 to <&0 on line 2 of your script, it works. Or simply drop that part entirely; read reads from standard input by default (that's pretty much its purpose), so there's no need to explicitly tell it to read from standard input.

If you want to read some particular input interactively and allow the remainder to be redirected from a file (or come through a pipe), you can do read </dev/tty.

And you don't need the semicolon statement separator after the END echo; the newline does just fine.

Похожие вопросы