How to make Bash scripts read from stdin

I needed to write some Bash scripts on Linux that read the input from stdin or a file passed as an optional argument, but couldn't figure how.

Googling turned up several designs and examples, such as on StackOverflow, where the script directly processes the input. But I actually wanted the script to assemble a pipeline, feed the input into the beginning, and delegate the processing to the programs and filters in the pipeline.

More googling turned up exactly what I wanted, a reply by the user Daniel buried in a long StackExchange thread.

The trick is to assign to a variable the input stream and feed it into the first program of the pipeline. To demonstrate the technique, the script unlc (unique line count) prints the number of unique lines in the input:

#!/usr/bin/env bash

# unlc - print number of unique lines in the optional input file or stdin
#
# Usage:
#
#   unlc [input-file]

input_file="${1:-/dev/stdin}"

cat "$input_file" | sort | uniq | wc -l

The code assigns to input_file the first argument $1 passed to the script, if supplied, or the standard input. Then cat feeds the content of input_file to the rest of the pipeline. The script is invoked by passing a file as an argument or feeding the data into the script's standard input:

$ cat input-file.txt 
1
2
2
3
4
4
4
4
$ unlc input-file.txt 
4
$ cat input-file.txt | unlc
4

Simple and brilliant.

#Linux

Discuss... Email | Reply @amoroso@fosstodon.org