This works as expected

$> cat ./readfromstdin.sh
echo reading
cat /dev/stdin

$> echo hello | ./readfromstdin.sh

I am trying to achieve something similar without a temporary file. My first attempt was

echo hello | (echo cat /dev/stdin|sh)

which did not work. With a heredoc it did not work either (though I am not sure what the right syntax would be:

echo hello | (cat << EOF | sh
cat /dev/stdin
pipe cmdsubst pipe heredoc>

Is it possible to read from stdin using a script piped to the shell?

  • 1
    I think you are looking for echo hello | sh -c 'echo reading; cat /dev/stdin' ? – Sundeep Apr 19 '17 at 9:15
  • 4
    It might help if you explained why you want to do this. This feels like it could be an XY problem, so explaining what your final objective is might get you more useful answers. For example, why don't you just use read instead of fiddling with /dev/stdin? – terdon Apr 19 '17 at 9:23

You can do what you describe relatively easily by piping to a subshell:

$ echo hello | ( echo reading; cat /dev/stdin )

I admit I can't really imagine any use case for this though. Why not just do:

$ echo hello | ( echo reading; read var; echo "$var")

That way you have the stdin contents saved as a variable and can manipulate them at your leisure.

$ echo 'world' |  { echo 'hello'; cat }

There's no need to explicitly give /dev/stdin to cat as that is what cat operates on by default if no other operands are given.

In your own code, it looks as if you want to pass a command rather than a string to output. That's how I interpret the presence of sh in the code anyway. I'm not entirely sure you need that though.

The problem you're having with doing that is due to feeding the script to sh on its standard input. The standard input will thus be reserved for commands, so piping a string into it won't work.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.