Accept pipeline and argument inputs in bash script

You can check to ensure there is stdin first, and if not, then use a command line argument instead if given:

#!/bin/bash
# Check to see if a pipe exists on stdin.
if [ -p /dev/stdin ]; then
        echo "Data was piped to this script!"
        # If we want to read the input line by line
        while IFS= read line; do
                echo "Line: ${line}"
        done
        # Or if we want to simply grab all the data, we can simply use cat instead
        # cat
else
        echo "No input was found on stdin, skipping!"
        # Checking to ensure a filename was specified and that it exists
        if [ -f "$1" ]; then
                echo "Filename specified: ${1}"
                echo "Doing things now.."
        else
                echo "No input given!"
        fi
fi

Then to test:

Let’s add some stuff to a test.txt file and then pipe the output to our script.

$ printf "stuff\nmore stuff\n" > test.txt
$ cat test.txt | ./testPipe.sh

Output:

Data was piped to this script!
Line: stuff 
Line: more stuff

Now let’s test if not providing any input:

$ ./testPipe.sh

Output:

No input was found on stdin, skipping! No input given!

Now let’s test if providing a valid filename:

$ ./testPipe.sh test.txt

Output:

No input was found on stdin, skipping!
Filename specified: test.txt
Doing things now..

And finally, let’s test using an invalid filename:

./testPipe.sh invalidFile.txt

Output:

No input was found on stdin, skipping!
No input given!

Explanation: Programs like read and cat will use the stdin if it is available within the shell, otherwise they will wait for input.

Source: