Send string to stdin

Viewed 213674

Is there a way to effectively do this in bash:

/my/bash/script < echo 'This string will be sent to stdin.'

I'm aware that I could pipe the output from the echo such as this:

echo 'This string will be piped to stdin.' | /my/bash/script
6 Answers

Solution

You want to (1) create stdout output in one process (like echo '…') and (2) redirect that output to stdin input of another process but (3) without the use of the bash pipe mechanism. Here's a solution that matches all three conditions:

/my/bash/script < <(echo 'This string will be sent to stdin.')

The < is normal input redirection for stdin. The <(…) is bash process substitution. Roughly it creates a /dev/fd/… file with the output of the substituting command and passes that filename in place of the <(…), resulting here for example in script < /dev/fd/123. For details, see this answer.

Comparison with other solutions

  • A one-line heredoc sent to stdin script <<< 'string' only allows to send static strings, not the output of other commands.

  • Process substitution alone, such as in diff <(ls /bin) <(ls /usr/bin), does not send anything to stdin. Instead, the process output is saved into a file, and its path is passed as a command line argument. For the above example, this is equivalent to diff /dev/fd/10 /dev/fd/11, a command where diff receives no input from stdin.

Use cases

I like that, unlike the pipe mechanism, the < <(…) mechanism allows to put the command first and all input after it, as is the standard for input from command line options.

However, beyond commandline aesthetics, there are some cases where a pipe mechanism cannot be used. For example, when a certain command has to be provided as argument to another command, such as in this example with sshpass.

cat | /my/bash/script

Enables one to type multiple lines into a program, without that input being saved in history, nor visible in ps. Finish with a newline then Ctrl + D to end cat.

aliases can and can't process piped stdin...

Here we create 3 lines of output

$ echo -e "line 1\nline 2\nline 3"
line 1
line 2
line 3

We then pipe the output to stdin of the sed command to put them all on one line

$ echo -e "line 1\nline 2\nline 3" |  sed -e ":a;N;\$!ba ;s?\n? ?g"
line 1 line 2 line 3

If we define an alias of the same sed command

$ alias oline='sed -e ":a;N;\$!ba ;s?\n? ?g"'

We can pipe the output to the stdin of the alias and it behaves exactly the same

$ echo -e "line 1\nline 2\nline 3" |  oline
line 1 line 2 line 3

The problem arises when we try to define the alias as a function

$ alias oline='function _oline(){ sed -e ":a;N;\$!ba ;s?\n? ?g";}_oline'

Defining the alias as a funstion breaks the pipe

$ echo -e "line 1\nline 2\nline 3" |  oline
>
Related