How can bash read from piped input or else from the command line argument

bash, pipe

Solution

You can read all of stdin into a variable with:

data=$(cat)

Note that what you're describing is non-canonical behavior. Good Unix citizens will:

- Read from a filename if supplied as an argument (regardless of whether stdin is a tty)

- Read from stdin if no file is supplied

This is what you see in `sed`, `grep`, `cat`, `awk`, `wc` and `nl` to name only a few.

Anyways, here's your example with the requested feature demonstrated:

$ cat script 
#!/bin/bash

if [ -t 0 ]
then
    echo nopipe
    data=$1
else
    echo pipe
    data=$(cat)
fi

echo "$data"

$ ./script 1234
nopipe
1234

$ echo 1234 | ./script
pipe
1234

Problem

I would like to read some data either from pipe or from the command line arguments (say `$1`), whichever is provided (priority has pipe). This fragment tells me if the pipe was open or not but I don't know what to put inside in order not to block the script (`test.sh`) (using `read` or `cat`) ``` if [ -t 0 ] then echo nopipe DATA=$1 else echo pipe # what here? # read from pipe into $DATA fi echo $DATA ``` Executing the `test.sh` script above I should get the following output: ``` $ echo 1234 | test.sh 1234 $ test.sh 123 123 $ echo 1234 | test.sh 123 1234 ```

Original source