🎁 New User? Get 20% off your first purchase with code NEWUSER20 Register Now →
Menu

Categories

getopts Command

Intermediate Shell Scripting man(1)

Parse command-line options in shell scripts

📅 Updated: Mar 16, 2026
SYNTAX
getopts OPTSTRING VARIABLE [ARGS]

What Does getopts Do?

The getopts command is a built-in shell utility for parsing command-line options (flags) in bash and POSIX shell scripts. It processes single-character options like -v, -f filename, and -h, following Unix conventions for command-line argument handling.

getopts is the standard way to make shell scripts accept options professionally, just like compiled programs. It handles option bundling (-vf instead of -v -f), options with arguments (-f filename), error reporting for unknown options, and the -- end-of-options marker.

Every production shell script that accepts arguments should use getopts. It replaces manual $1/$2 parsing with a robust, standard approach that handles edge cases correctly. While getopt (external command, note the different name) supports long options (--verbose), getopts (built-in) is more portable and sufficient for most scripts.

Options & Flags

OptionDescriptionExample
OPTSTRING String of valid option characters (colon after = requires argument) "vf:o:h" means -v, -f ARG, -o ARG, -h
VARIABLE Variable to store the current option character while getopts "vf:h" opt; do
$OPTARG Contains the argument for the current option (if colon in optstring) case $opt in f) file=$OPTARG ;;
$OPTIND Index of the next argument to process shift $((OPTIND - 1))
Leading : Silent error mode — suppress error messages getopts ":vf:h" opt
? Matches unknown/invalid options case $opt in ?) echo "Invalid: -$OPTARG" ;;

Practical Examples

#1 Basic option parsing

Complete option parsing: -v (flag), -f file (with argument), -o output (with argument), -h (help). Shift removes parsed options leaving positional args.
$ #!/bin/bash while getopts "vf:o:h" opt; do case $opt in v) verbose=true ;; f) input_file=$OPTARG ;; o) output_file=$OPTARG ;; h) echo "Usage: $0 [-v] [-f file] [-o output] [-h]"; exit 0 ;; *) echo "Invalid option: -$OPTARG" >&2; exit 1 ;; esac done shift $((OPTIND - 1))

#2 Script with verbose mode

Simple verbose flag. After getopts, $1 contains the first non-option argument.
$ #!/bin/bash verbose=false while getopts "v" opt; do case $opt in v) verbose=true ;; esac done shift $((OPTIND - 1)) [ "$verbose" = true ] && echo "Processing: $1" # do work with $1...

#3 Required argument validation

Handle missing arguments (leading colon enables silent mode). Check required options after parsing.
$ #!/bin/bash while getopts ":f:" opt; do case $opt in f) file=$OPTARG ;; :) echo "Option -$OPTARG requires an argument" >&2; exit 1 ;; ?) echo "Unknown option: -$OPTARG" >&2; exit 1 ;; esac done [ -z "$file" ] && echo "Error: -f is required" >&2 && exit 1

#4 Backup script with options

A practical backup script accepting source, destination, compression flag, and verbose mode.
$ #!/bin/bash usage() { echo "Usage: $0 -s source -d dest [-c] [-v]"; exit 1; } while getopts "s:d:cvh" opt; do case $opt in s) src=$OPTARG ;; d) dst=$OPTARG ;; c) compress=true ;; v) verbose=true ;; h) usage ;; *) usage ;; esac done [ -z "$src" ] || [ -z "$dst" ] && usage

#5 Option bundling works

getopts handles bundled options: -cv is the same as -c -v. Options with arguments (-f) can be bundled too: -cvf input.txt.
$ ./script.sh -cv -f input.txt

Tips & Best Practices

Always shift after getopts: After the getopts loop, run: shift $((OPTIND - 1)). This removes parsed options, leaving only positional arguments in $1, $2, etc.
getopts vs getopt: getopts (built-in, POSIX) handles short options only. getopt (external, GNU) supports long options (--verbose). getopts is more portable; use getopt when you need long options.
Reset OPTIND for functions: OPTIND is global. If calling getopts in a function, set local OPTIND=1 first, or pass arguments explicitly to avoid conflicts with the main script.
Use leading colon for custom errors: Start optstring with : (e.g., ":vf:h") to suppress default error messages. Handle errors yourself in the ? and : cases for cleaner output.

Frequently Asked Questions

How do I parse command-line arguments in bash?
Use getopts in a while loop: while getopts "vf:h" opt; do case $opt in v) verbose=1 ;; f) file=$OPTARG ;; h) usage ;; esac; done; shift $((OPTIND-1))
Does getopts support long options (--verbose)?
No. getopts only supports single-character options (-v). For long options, use the external getopt command or parse manually with a case statement.
What does the colon after a letter mean in getopts?
A colon after a letter means that option requires an argument. "f:" means -f requires an argument (stored in $OPTARG). Without colon, it is a boolean flag.
How do I make an option required?
getopts does not enforce required options. Check after the loop: [ -z "$file" ] && echo "Error: -f required" && exit 1. This is the standard pattern.

Master Linux with Professional eBooks

Curated IT eBooks covering Linux, DevOps, Cloud, and more

Browse Books →