Bash Input Handling: stdin, read, and Command Arguments

As soon as a script needs to adapt per run, you need input handling. In Bash, that usually means a mix of stdin, read, and positional arguments.

Table of Contents

This post covers the most practical ways to pass data into scripts.

stdin and Interactive Input

Structured Input Techniques

Positional Parameters and Argument Flow

Series Navigation

stdin and interactive input

How stdin works in scripts

stdin is the default stream scripts read from when they are piped data or when you call read.

echo "alpha" | ./consume.sh

Inside consume.sh:

#!/usr/bin/env bash

read -r value
echo "value from stdin: $value"

Using read with prompts

read -p gives a user prompt for interactive usage.

#!/usr/bin/env bash

read -p "Enter environment name: " env_name
echo "Selected environment: $env_name"

Protecting raw input with read -r

-r prevents backslash escaping, which keeps paths and literal input intact.

read -r path_value

When input may include spaces, quote it in later usage.

Structured input techniques

Here documents for multi-line input

Use a here document when you need embedded multi-line text.

cat <<EOF > message.txt
Hello team
This file was generated by a script
EOF

You can also feed command input:

mysql -u app -p <<SQL
SELECT NOW();
SQL

Here strings for short inline values

A here string is a concise way to send one value to stdin.

grep "prod" <<< "dev prod stage"

Positional parameters and argument flow

Core argument variables

Bash gives special variables for script arguments.

#!/usr/bin/env bash

echo "script name: $0"
echo "first arg: $1"
echo "arg count: $#"
echo "all args as separate words: $@"
echo "all args as one word: $*"

Quote “$@” correctly

Always quote "$@" when forwarding arguments to preserve word boundaries.

#!/usr/bin/env bash

run_command() {
  echo "running: $*"
  command "$@"
}

Parse simple flags with shift

shift moves arguments left so you can process them one by one.

#!/usr/bin/env bash

name=""
verbose=false

while [[ $# -gt 0 ]]; do
  case "$1" in
    --name)
      name="$2"
      shift 2
      ;;
    --verbose)
      verbose=true
      shift
      ;;
    *)
      echo "unknown argument: $1"
      exit 1
      ;;
  esac
done

echo "name=$name verbose=$verbose"

Practical example

This script accepts a positional argument and falls back to interactive input.

#!/usr/bin/env bash

name="${1:-}"

if [[ -z "$name" ]]; then
  read -r -p "Enter your name: " name
fi

printf "Hello, %s\n" "$name"

Next in this series

Next, we will build branching logic with if, elif, and else so your script can react to conditions and command outcomes.