I love getopt to parse options from the argv
argument. Unfortunately I'm not able to make getopt
parse options that are between nonoptions or at the end of argv
. Example Program:
#include <stdio.h>
#include <unistd.h>
int o_help = 0;
int main(int argc, char *argv[]) {
int opt, i;
while ((opt = getopt(argc, argv, "h")) != -1) {
switch (opt) {
case 'h':
o_help = 1;
break;
default:
return -1;
}
}
printf("o_help=%d\n", o_help);
for (i = 1; i < argc; i++) {
printf("%s ", argv[i]);
}
printf("\n");
return 0;
}
Running the program in an alpine container on macOS Mojave, I get the following outputs:
$ gcc prog.c
$ ./a.out hello -h world
o_help=0
hello -h world
$ ./a.out -h hello world
o_help=1
-h hello world
The official getopt
man page states:
By default, getopt() permutes the contents of argv as it scans, so that eventually all the nonoptions are at the end.
Since I did not specify otherwise, I expect the default behaviour to 1. parse the -h
option and 2. permute argv
so that the nonoptions are at the end of the array. Unfortunately, calling the program like ./a.out hello -h world
does neither parse -h
nor permute the array. Help would be greatly appreciated.
Marco's answer is correct, but "install glibc by yourself" is really not a good suggestion if you're not using a glibc-based distribution; you'd be building a whole parallel library ecosystem by yourself. There are a couple canonical solutions to your problem that are much easier.
The GNU-endorsed method of using nonstandard GNU behaviors like the one you want is to use gnulib and autoconf, which can automatically replace getopt with a GNU version as needed. However that's a heavy change and it requires your program to be GPL'd.
A much easier solution is just using getopt_long
with a degenerate list of long options, instead of getopt
. Since getopt_long
is not a standard-governed function but an extension originally define on GNU, musl's implementation of it is free to follow the GNU behavior of permuting argv
to allow mixed options and non-option arguments, and does so.