getopt(3)

๐ŸŒธ NAME ๐ŸŒธ

getopt, optarg, optind, opterr, optopt โ€” bestie, this is the function that parses your command-line options for you ๐Ÿ’…


๐Ÿซถ LIBRARY ๐Ÿซถ

Standard C library (libc, link it with -lc)


โœจ SYNOPSIS โœจ

#include <unistd.h>

int getopt(int argc, char *argv[],
           const char *optstring);

extern char *optarg;
extern int optind, opterr, optopt;

๐ŸŽ€ Feature Test Macro Requirements for glibc ๐ŸŽ€

(go check feature_test_macros(7) if you're nosy about these)

  • getopt(): _POSIX_C_SOURCE >= 2 || _XOPEN_SOURCE

๐Ÿ’– DESCRIPTION ๐Ÿ’–

Okay so getopt() parses the command-line arguments. Their arguments argc and argv are literally the argument count and the argument array just as they got passed to your main() when the program got invoked. An element of argv that starts with - โ€” and is not exactly "-" or "--" โ€” is an option element, no cap. The characters inside that element (aside from that leading -) are the option characters. And if you call getopt() in a loop over and over, it just hands you each option character from each option element, one at a time. Iconic.

The variable optind is the index of the next element in argv that's gonna get processed. The system initializes it to 1. You can reset it back to 1 to restart scanning the same argv, or whenever you're scanning a brand new argument vector. Slay.

If getopt() finds another option character, it returns that character, and it updates the external variable optind plus a static variable nextchar so that the next call to getopt() can pick up right where it left off โ€” with the next option character or the next argv-element. Obsessed with the continuity honestly.

If there are no more option characters, getopt() returns -1. And at that point optind is the index in argv of the first argv-element that is not an option. ๐Ÿฆ‹

optstring is a string holding all the legitimate option characters. And a legitimate option character is, like, any visible one-byte ascii(7) character (one where isgraph(3) would return nonzero, iykyk) that isn't '-', ':', or ';'. If one of those characters is followed by a colon, then that option requires an argument, so getopt() puts a pointer to the following text โ€” either the text in that same argv-element, or the text of the following argv-element โ€” into optarg.

Two colons mean the option takes an optional arg. In that case, if there's text in the current argv-element (like, in the same word as the option name itself, for example "-oarg"), then it gets returned in optarg; otherwise optarg is set to zero. Heads up: this is a GNU extension โœจ

If optstring contains W followed by a semicolon, then -W foo gets treated as the long option --foo. (The -W option is reserved by POSIX.2 for implementation extensions, so don't get weird with it.) This behavior is a GNU extension too โ€” and it's not available with libraries before glibc 2 โš ๏ธ

By default, getopt() permutes the contents of argv as it scans, so eventually all the nonoptions end up at the end. But there are two other scanning modes implemented as well:

  • If the first character of optstring is '+', or the environment variable POSIXLY_CORRECT is set, then option processing stops the moment a nonoption argument shows up. And if '+' is not the first character of optstring, it's treated as a normal option. So if you need that POSIXLY_CORRECT behavior in that case, optstring is gonna contain two '+' symbols.
  • If the first character of optstring is '-', then every nonoption argv-element gets handled as if it were the argument of an option whose character code is 1. (This one is used by programs that were written expecting options and other argv-elements in any order, and that genuinely care about the ordering of the two.)

The special argument "--" forces an end to option-scanning regardless of whatever scanning mode you're in, periodt.

While it's processing the option list, getopt() can detect two kinds of errors:

  1. an option character that wasn't specified in optstring, and
  2. a missing option argument (i.e., an option sitting at the end of the command line without the argument it expected ๐Ÿฅบ)

These errors get handled and reported like this:

  • By default, getopt() prints an error message on standard error, places the erroneous option character in optopt, and returns '?' as the function result.
  • If the caller has set the global variable opterr to zero, then getopt() does not print an error message. The caller can figure out that there was an error by testing whether the return value is '?'. (By default, opterr has a nonzero value.)
  • If the first character (following any optional '+' or '-' described above) of optstring is a colon (':'), then getopt() likewise does not print an error message. And on top of that, it returns ':' instead of '?' to signal a missing option argument. This is the move that lets the caller tell the two different types of errors apart ๐Ÿ’…

๐Ÿ”ฅ RETURN VALUE ๐Ÿ”ฅ

If an option was successfully found, then getopt() returns the option character. If all command-line options have been parsed, then getopt() returns -1. If getopt() encounters an option character that wasn't in optstring, then '?' is returned. And if getopt() encounters an option with a missing argument, then the return value depends on the first character in optstring: if it's ':', then ':' is returned; otherwise '?' is returned.


๐ŸŒˆ ENVIRONMENT ๐ŸŒˆ

  • POSIXLY_CORRECT โ€” if this is set, then option processing stops the second a nonoption argument is encountered.

๐Ÿ‘‘ ATTRIBUTES ๐Ÿ‘‘

For an explanation of all the terms used in this section, go peek at attributes(7).

  • Interface: getopt()
  • Attribute: Thread safety
  • Value: MT-Unsafe race:getopt env

๐Ÿฆ‹ VERSIONS ๐Ÿฆ‹

POSIX specifies that the argv array argument should be const, but these functions permute its elements unless the environment variable POSIXLY_CORRECT is set. const is used in the actual prototype so it stays compatible with other systems; however, this page doesn't show the qualifier, just to avoid confusing readers. Bestie behavior honestly.


๐Ÿ’œ STANDARDS ๐Ÿ’œ

  • getopt() โ€” POSIX.1-2008.
    • The use of '+' and '-' in optstring is a GNU extension.

๐ŸŽ€ HISTORY ๐ŸŽ€

  • getopt() โ€” POSIX.1-2001, and POSIX.2.

On some older implementations, getopt() was declared in <stdio.h>. SUSv1 permitted the declaration to appear in either <unistd.h> or <stdio.h>. POSIX.1-1996 marked the use of <stdio.h> for this purpose as LEGACY ๐Ÿ’€. POSIX.1-2001 does not require the declaration to appear in <stdio.h>.

Very old versions of glibc were affected by a _PID_GNU_nonoption_argv_flags_ environment variable. Ancient lore fr fr.


๐Ÿ™ˆ NOTES ๐Ÿ™ˆ

A program that scans multiple argument vectors, or rescans the same vector more than once, and that wants to make use of GNU extensions like '+' and '-' at the start of optstring, or that changes the value of POSIXLY_CORRECT between scans, must reinitialize getopt() by resetting optind to 0 โ€” not the traditional value of 1. (Resetting to 0 forces the invocation of an internal initialization routine that rechecks POSIXLY_CORRECT and checks for GNU extensions in optstring.) Don't skip this step, it's giving "I read the docs" energy โœจ

Command-line arguments are parsed in strict order, meaning that an option requiring an argument will consume the next argument, regardless of whether that argument is the correctly specified option argument or simply the next option โ€” in the scenario where the user mis-specifies the command line ๐Ÿ˜ญ. For example, if optstring is specified as "1n:" and the user specifies the command line arguments incorrectly as prog -n -1, the -n option will be given the optarg value "-1", and the -1 option will be considered to have not been specified.


โญ EXAMPLES โญ

๐Ÿ’– getopt() ๐Ÿ’–

The following trivial example program uses getopt() to handle two program options: -n, with no associated value; and -t val, which expects an associated value.

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int
main(int argc, char *argv[])
{
    int flags, opt;
    int nsecs, tfnd;

    nsecs = 0;
    tfnd = 0;
    flags = 0;
    while ((opt = getopt(argc, argv, "nt:")) != -1) {
        switch (opt) {
        case 'n':
            flags = 1;
            break;
        case 't':
            nsecs = atoi(optarg);
            tfnd = 1;
            break;
        default: /* '?' */
            fprintf(stderr, "Usage: %s [-t nsecs] [-n] name\n",
                    argv[0]);
            exit(EXIT_FAILURE);
        }
    }

    printf("flags=%d; tfnd=%d; nsecs=%d; optind=%d\n",
           flags, tfnd, nsecs, optind);

    if (optind >= argc) {
        fprintf(stderr, "Expected argument after options\n");
        exit(EXIT_FAILURE);
    }

    printf("name argument = %s\n", argv[optind]);

    /* Other code omitted */

    exit(EXIT_SUCCESS);
}

๐ŸŒธ SEE ALSO ๐ŸŒธ

getopt(1), getopt_long(3), getopt_long_only(3), getsubopt(3)


okay that's the whole page, you ate it, go parse some options ๐Ÿ’…

this little rewrite was brought to you by Linux man-pages 6.20, dated 2026-02-08 โ€” mwah, take care bestie ๐Ÿซถ

๐Ÿ“ฆ where this page comes from
  • arch rolling: man-pages 6.20-1 ยท BSD-2-Clause AND BSD-3-Clause AND BSD-4.3TAHOE AND BSD-4-Clause-UC AND GPL-1.0-or-later AND GPL-2.0-only AND GPL-2.0-or-later AND GPL-3.0-or-later AND LGPL-3.0-linking-exception AND LGPL-3.0-or-later AND LicenseRef-Public-Domain AND LicenseRef-UltraPermissive AND Linux-man-pages-1-para AND Linux-man-pages-copyleft AND Linux-man-pages-copyleft-2-para AND Linux-man-pages-copyleft-var AND MIT AND Spencer-94
  • nixpkgs unstable: man-pages 6.20
  • ๐Ÿ“œ the page's license: Linux-man-pages-copyleft
  • ๐Ÿ’– girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms