{"id":11879,"date":"2025-09-09T03:00:00","date_gmt":"2025-09-09T07:00:00","guid":{"rendered":"https:\/\/www.both.org\/?p=11879"},"modified":"2025-09-08T11:11:11","modified_gmt":"2025-09-08T15:11:11","slug":"reading-the-command-line-with-getopt","status":"publish","type":"post","link":"https:\/\/www.both.org\/?p=11879","title":{"rendered":"Reading the command line with getopt"},"content":{"rendered":"<div class=\"pld-like-dislike-wrap pld-template-1\">\r\n    <div class=\"pld-like-wrap  pld-common-wrap\">\r\n    <a href=\"javascript:void(0)\" class=\"pld-like-trigger pld-like-dislike-trigger  \" title=\"\" data-post-id=\"11879\" data-trigger-type=\"like\" data-restriction=\"cookie\" data-already-liked=\"0\">\r\n                        <i class=\"fas fa-thumbs-up\"><\/i>\r\n                <\/a>\r\n    <span class=\"pld-like-count-wrap pld-count-wrap\">    <\/span>\r\n<\/div><\/div>\n<p>Writing a C program to process files is easy when you already know what files you&#8217;ll operate on and what actions to take. If you &#8220;hard code&#8221; the filename into your program, or if your program is coded to do things only one way, then your program will know exactly what to do. That makes it very easy to write.<\/p>\n\n\n\n<p>But a program that uses &#8220;hard coded&#8221; values like that will be very limited because <em>it can only do that one thing<\/em>. Instead, you can make your program\u00a0much more flexible if it can <em>respond to the user every time the program runs<\/em>. Let your user tell your program what files to use or how to do things differently. And for that, you need to read the command line.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"reading-the-command-line\">Reading the command line<\/h2>\n\n\n\n<p>When you write a program in C, you might start with the declaration:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>int main()<\/code><\/pre>\n\n\n\n<p>That&#8217;s the simplest way to start a C program. But if you add these standard parameters in the parentheses, your program can read the options given to it on the command line:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>int main(int argc, char **argv)<\/code><\/pre>\n\n\n\n<p>The <code>argc<\/code> variable is the argument count or the number of arguments on the command line. This will always be a number that&#8217;s at least one.<\/p>\n\n\n\n<p>The <code>argv<\/code> variable is a double pointer, an array of strings, that contains the arguments from the command line. The first entry in the array, <code>argv[0]<\/code>, is always the name of the program. The other elements of the <code>**argv<\/code> array contain the rest of the command-line arguments.<\/p>\n\n\n\n<p>I&#8217;ll write a simple program to echo back the options given to it on the command line. This is similar to the Linux <code>echo<\/code> command, except it also prints the name of the program. It also prints each command-line option on its own line using the <code>puts<\/code> function:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>#include &lt;stdio.h&gt;\n\nint\nmain(int argc, char **argv)\n{\n  int i;\n\n  printf(\"argc=%d\\n\", argc); \/* debugging *\/\n\n  for (i = 0; i &lt; argc; i++) {\n    puts(argv&#91;i]);\n  }\n\n  return 0;\n}<\/code><\/pre>\n\n\n\n<p>Compile this program and run it with a few command-line arguments, such as a few extra words, and you&#8217;ll see your command line <em>printed back to you and each item on its own line<\/em>:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ .\/echo this program can read the command line\nargc=8\n.\/echo\nthis\nprogram\ncan\nread\nthe\ncommand\nline<\/code><\/pre>\n\n\n\n<p>This command line sets the program&#8217;s <code>argc<\/code> to <code>8<\/code>, and the <code>**argv<\/code> array contains eight entries: the name of the program, plus the seven words the user entered. And as always in C programs, the array starts at zero, so the elements are numbered 0, 1, 2, 3, 4, 5, 6, 7. That&#8217;s why you can process the command line with the <code>for<\/code> loop using the comparison <code>i &lt; argc<\/code>.<\/p>\n\n\n\n<p>You can use this to write your own versions of the Linux <code>cat<\/code> or <code>cp<\/code> commands. The <code>cat<\/code> command&#8217;s basic functionality displays the contents of one or more files. Here&#8217;s a simple version of <code>cat<\/code> that reads the filenames from the command line:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>#include &lt;stdio.h&gt;\n\nvoid\ncopyfile(FILE *in, FILE *out)\n{\n  int ch;\n\n  while ((ch = fgetc(in)) != EOF) {\n    fputc(ch, out);\n  }\n}\n\nint\nmain(int argc, char **argv)\n{\n  int i;\n  FILE *fileptr;\n\n  for (i = 1; i &lt; argc; i++) {\n    fileptr = fopen(argv&#91;i], \"r\");\n\n    if (fileptr != NULL) {\n      copyfile(fileptr, stdout);\n      fclose(fileptr);\n    }\n  }\n\n  return 0;\n}<\/code><\/pre>\n\n\n\n<p>This simple version of <code>cat<\/code> reads a list of filenames from the command line and displays the contents of each file to the standard output, one character at a time. For example, if I have one file called <code>hello.txt<\/code> that contains a few lines of text, I can display its contents with my own <code>cat<\/code> command:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ .\/cat hello.txt \nHi there!\nThis is a sample text file.<\/code><\/pre>\n\n\n\n<p>Using this sample program as a starting point, you can write your own versions of other Linux commands, such as the <code>cp<\/code> program, by reading only two filenames: one file to read from and another file to write the copy.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"reading-command-line-options\">Reading command-line options<\/h2>\n\n\n\n<p>Reading filenames and other text from the command line is great, but what if you want your program to change its behavior based on the&nbsp;<em>options<\/em> the user gives it? For example, the Linux <code>cat<\/code> command supports several command-line options, including:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>-b Put line numbers next to non-blank lines<\/li>\n\n\n\n<li>-E Show the ends of lines as <code>$<\/code><\/li>\n\n\n\n<li>-n Put line numbers next to all lines<\/li>\n\n\n\n<li>-s Suppress printing repeated blank lines<\/li>\n\n\n\n<li>-T Show tabs as <code>^I<\/code><\/li>\n\n\n\n<li>-v Verbose; show non-printing characters using <code>^x<\/code> and <code>M-x<\/code> notation, except for new lines and tabs<\/li>\n<\/ul>\n\n\n\n<p>These <em>single-letter<\/em> options are called <em>short options<\/em>, and they always start with a single hyphen character. You usually see these short options written separately, such as <code>cat -E -n<\/code>, but you can also combine the short options into a single <em>option string<\/em> such as <code>cat -En<\/code>.<\/p>\n\n\n\n<p>Fortunately, there&#8217;s an easy way to read these from the command line. All Linux and Unix systems include a special C library called <code>getopt<\/code>, defined in the <code>unistd.h<\/code> header file. You can use <code>getopt<\/code> in your program to read these short options.<\/p>\n\n\n\n<p>Unlike other Unix systems, <code>getopt<\/code> on Linux will always ensure your short options appear at the front of your command line. For example, say a user types <code>cat -E file -n<\/code>. The <code>-E<\/code> option is upfront, but the <code>-n<\/code> option is after the filename. But if you use Linux <code>getopt<\/code>, your program will always behave as though the user types <code>cat -E -n file<\/code>. That makes processing a breeze because <code>getopt<\/code> can parse the short options, leaving you a list of filenames on the command line that your program can read using the <code>**argv<\/code> array.<\/p>\n\n\n\n<p>You use <code>getopt<\/code> like this:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>#include &lt;unistd.h>\n\nint getopt(int argc, char **argv, char *optstring);<\/code><\/pre>\n\n\n\n<p>The option string <code>optstring<\/code> contains a list of the valid option characters. If your program only allows the <code>-E<\/code> and <code>-n<\/code> options, you use &#8220;<code>En\"<\/code> as your option string.<\/p>\n\n\n\n<p>You usually use <code>getopt<\/code> in a loop to parse the command line for options. At each <code>getopt<\/code> call, the function returns the next short option it finds on the command line or the value <code>'?'<\/code> for any unrecognized short options. When <code>getopt<\/code> can&#8217;t find any more short options, it returns <code>-1<\/code> and sets the global variable <code>optind<\/code> to the next element in <code>**argv<\/code> after all the short options.<\/p>\n\n\n\n<p>Let&#8217;s look at a simple example. This demo program isn&#8217;t a full replacement of <code>cat<\/code> with all the options, but it can parse its command line. Every time it finds a valid command-line option, it prints a short message to indicate it was found. In your own programs, you might instead set a variable or take some other action that responds to that command-line option:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>#include &lt;stdio.h&gt;\n#include &lt;unistd.h&gt;\n\nint\nmain(int argc, char **argv)\n{\n  int i;\n  int option;\n\n  \/* parse short options *\/\n\n  while ((option = getopt(argc, argv, \"bEnsTv\")) != -1) {\n    switch (option) {\n    case 'b':\n      puts(\"Put line numbers next to non-blank lines\");\n      break;\n    case 'E':\n      puts(\"Show the ends of lines as $\");\n      break;\n    case 'n':\n      puts(\"Put line numbers next to all lines\");\n      break;\n    case 's':\n      puts(\"Suppress printing repeated blank lines\");\n      break;\n    case 'T':\n      puts(\"Show tabs as ^I\");\n      break;\n    case 'v':\n      puts(\"Verbose\");\n      break;\n    default:                          \/* '?' *\/\n      puts(\"What's that??\");\n    }\n  }\n\n  \/* print the rest of the command line *\/\n\n  puts(\"------------------------------\");\n\n  for (i = optind; i &lt; argc; i++) {\n    puts(argv&#91;i]);\n  }\n\n  return 0;\n}<\/code><\/pre>\n\n\n\n<p>If you compile this program as <code>args<\/code>, you can try out different command lines to see how they parse&nbsp;the short options and always leave&nbsp;you with the rest of the command line. In the simplest case, with all the options up front, you get this:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ .\/args -b -T file1 file2\nPut line numbers next to non-blank lines\nShow tabs as ^I\n------------------------------\nfile1\nfile2<\/code><\/pre>\n\n\n\n<p>Now try the same command line but combine the two short options into a single option string:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ .\/args -bT file1 file2\nPut line numbers next to non-blank lines\nShow tabs as ^I\n------------------------------\nfile1\nfile2<\/code><\/pre>\n\n\n\n<p>If necessary, <code>getopt<\/code> can &#8220;reorder&#8221; the command line to deal with short options that are out of order:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ .\/args -E file1 file2 -T\nShow the ends of lines as $\nShow tabs as ^I\n------------------------------\nfile1\nfile2<\/code><\/pre>\n\n\n\n<p>If your user gives an incorrect short option, <code>getopt<\/code> prints a message:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ .\/args -s -an file1 file2\nSuppress printing repeated blank lines\n.\/args: invalid option -- 'a'\nWhat's that??\nPut line numbers next to all lines\n------------------------------\nfile1\nfile2<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<p><em>This article is adapted from <a href=\"https:\/\/opensource.com\/article\/21\/8\/short-option-parsing-c\">Short option parsing using getopt in C<\/a> by Jim Hall, and is republished with the author&#8217;s permission.<\/em><\/p>\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>You can make your program much more flexible if it can respond to the user every time the program runs.<\/p>\n","protected":false},"author":33,"featured_media":3096,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_lmt_disableupdate":"","_lmt_disable":"","footnotes":""},"categories":[100,150],"tags":[104,152],"class_list":["post-11879","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-command-line","category-programming","tag-command-line","tag-programming"],"modified_by":"Jim Hall","_links":{"self":[{"href":"https:\/\/www.both.org\/index.php?rest_route=\/wp\/v2\/posts\/11879","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.both.org\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.both.org\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.both.org\/index.php?rest_route=\/wp\/v2\/users\/33"}],"replies":[{"embeddable":true,"href":"https:\/\/www.both.org\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=11879"}],"version-history":[{"count":2,"href":"https:\/\/www.both.org\/index.php?rest_route=\/wp\/v2\/posts\/11879\/revisions"}],"predecessor-version":[{"id":11881,"href":"https:\/\/www.both.org\/index.php?rest_route=\/wp\/v2\/posts\/11879\/revisions\/11881"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.both.org\/index.php?rest_route=\/wp\/v2\/media\/3096"}],"wp:attachment":[{"href":"https:\/\/www.both.org\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=11879"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.both.org\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=11879"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.both.org\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=11879"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}