I would like a Bash script that can take input from a file or stdin, much like grep
, for example
$ cat hw.txt
Hello world
$ grep wor hw.txt
Hello world
$ echo 'Hello world' | grep wor
Hello world
$ grep wor <<< 'Hello world'
Hello world
all works beautifully. However with the following script
read b < "${1-/dev/stdin}"
echo $b
It fails if using a herestring
$ hw.sh hw.txt
Hello world
$ echo 'Hello world' | hw.sh
Hello world
$ hw.sh <<< 'Hello world'
/opt/a/hw.sh: line 1: /dev/stdin: No such file or directory
Using
/dev/stdin
in this manner can be problematic because you are attempting to get a handle to stdin using a name in the filesystem (/dev/stdin
) rather than using the file descriptor which bash has already handed you as stdin (file descriptor 0).Here's a small script for you to test:
On my cygwin installation this produces the following:
What this output shows is that bash is creating a temporary file to hold your HERE document (
/tmp/sh-thd-1362969584
) and making it available on file descriptor 0, stdin. However, the temporary file has already been unlinked from the file system and so is not accessible by reference through a file system name such as/dev/stdin
. You can get the contents by reading file descriptor 0, but not by trying to open/dev/stdin
.On Linux, the
./s
script above gives the following, showing that the file has been unlinked:Change your script to use the stdin supplied, rather than trying to reference through
/dev/stdin
.bash
parses some file names (like/dev/stdin
) specially, so that they are recognized even if they are not actually present in the file system. If your script doesn't have#!/bin/bash
at the top, and/dev/stdin
isn't in your file system, your script may be run using/bin/sh
, which would expect/dev/stdin
to actually be a file.(This should, perhaps, not be an answer, but rather a comment to Austin's answer.)
No problem for me. I'm using bash 4.2.42 on Mac OS X.
You got a typo here
Try