Recently, we needed to start an application using a script, which application had its own CLI.
After starting it, we had to feed it with some input to configure it before handing it over to the end user.
The application we used was named dog
. We wrote into a plain text file (named food
) the commands that we needed to feed the application and then we started the execution using a plain input redirect like so dog < food;
.
Doing so, resulted into properly feeding the dog
application the food
data but it would cause the application to terminate immediately after the food
was done as it would also feed the EOF
(End Of File
) directive to dog
.
Apparently, the application after receiving the EOF
, it would then terminate without allowing the end user to take control.
To mitigate the problem, we used the cat
command to concatenate the input file along with the stdin
stream, permitting us to first feed all the data in the food
file and then allow the user to input data using the standard input stream.
Our final command resulted in the following solution as below
cat <(cat food) - | dog;
Where -
is the special sign for standard input stdin
.
cat food
can be of course replaced with other commands that produce output on the standard output (stdout
).
A bad side-effect of this solution, is that we lost some functionality of the terminal including, but not limited to, using the backspace and navigation.
This post is also available in: Greek
If dog was a bash script, it is possible to read from stdin if it was redirected, reset stdin back to the terminal if it was redirected, and then read from the terminal. Doing so addresses the backspace and navigation issues. Here is an example of how it could be done:
#/usr/bin/env bash
#
# This script reads any piped or redirected text from stdin
# then prompts user for an interactive response.
#
# $ ./dog
# Enter a string? For cats
# String entered: For cats
#
# $ echo -e “This is\nfood” | ./dog
# Text supplied: This is
# Text supplied: food
# Enter a string? For cats
# String entered: For cats
#
# $ ./dog < EOF
# Text supplied: This is
# Text supplied: food
# Enter a string? For cats
# String entered: For cats
# read from stdin if stdin was piped or redirected
if [[ ! -t 0 ]]
then
while read line
do
echo “Text supplied: $line”
done
# reset stdin to read from terminal
exec 0 /dev/tty
fi
# prompt for more input
read -p “Enter a string? ” string
echo “String entered: ” $string