{"id":14036,"date":"2026-04-27T03:00:00","date_gmt":"2026-04-27T07:00:00","guid":{"rendered":"https:\/\/www.both.org\/?p=14036"},"modified":"2026-04-15T12:15:07","modified_gmt":"2026-04-15T16:15:07","slug":"writing-a-replacement-seq-command","status":"publish","type":"post","link":"https:\/\/www.both.org\/?p=14036","title":{"rendered":"Writing a replacement seq command"},"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=\"14036\" 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>One Unix command I never remember how to use properly is the <strong>seq<\/strong> command to produce a list of numbers. This is a simple but useful program when you need to test a program that works on text, because you know exactly what it will produce and how much it will print. Unfortunately, the usage changes if you use one, two, or three command line options\u2014so I always have to look up the <strong>man<\/strong> page to remind myself how to use it. I had to look it up again so I could write this article:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>seq<\/strong> by itself prints the numbers 1 to 10<\/li>\n\n\n\n<li><strong>seq i<\/strong> prints the numbers 1 to <strong>i<\/strong><\/li>\n\n\n\n<li><strong>seq i j<\/strong> prints the numbers from i to <strong>j<\/strong>, incrementing by 1<\/li>\n\n\n\n<li><strong>seq i j k<\/strong> prints the numbers from i to <strong>k<\/strong>, incrementing by <strong>j<\/strong><\/li>\n<\/ul>\n\n\n\n<p>I never remember that off the top of my head, because each command line usage has a different arrangement of the start, stop, and step values. But the benefit to knowing a little programming means you can create your own version of the command that makes sense for how you use it. So let&#8217;s do that.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">A new loop<\/h2>\n\n\n\n<p>The <strong>DO<\/strong> loop in FORTRAN makes a lot of sense for a command to list numbers, but that&#8217;s probably a function of having learned FORTRAN during my undergrad days. The <strong>DO<\/strong> loop is just a <strong>for<\/strong> loop in any other programming language, but the usage looks like this:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>DO start, stop, step<\/code><\/pre>\n\n\n\n<p>That&#8217;s also an easy-to-remember command line usage to create a list of numbers. I call my version of the program <strong>num<\/strong>, because it prints <em>num<\/em>bers. The usage looks like this:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>num &#91; start &#91; stop &#91; step ]]]<\/code><\/pre>\n\n\n\n<p>The default case will count from 1 to 10, incrementing by 1. Or if I write <strong>num 5<\/strong>, it should print from 5 to 10. If I give it <strong>num 1 5<\/strong>, it should print 1 to 5. And if I run it like <strong>num 10 0 -1<\/strong>, it should count down from 10 to zero.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">A sample implementation<\/h2>\n\n\n\n<p>This command line usage turns out to be really easy to implement as a program. Because the program always knows the first option is the start value, the second is always the end, and the third is always the step, the program just evaluates the command line count for each, then uses a function to turn the command line string into a number:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>   if (argc &gt; 1) {\n        start = atoi(argv&#91;1]);\n\n\n        if (argc &gt; 2) {\n            stop = atoi(argv&#91;2]);\n\n\n            if (argc &gt; 3) {\n                step = atoi(argv&#91;3]);\n\n\n                if (argc &gt; 4) {\n                    fputs(\"usage: num &#91; start &#91; stop &#91; step ]]]\\n\", stderr);\n                    fputs(\"extra options ignored\\n\", stderr);\n                }\n            }\n        }\n    }<\/code><\/pre>\n\n\n\n<p>This block only collects the command line arguments and turns them into start, stop and step values. Now, we&#8217;re ready to print the list of numbers. This is just a <strong>for<\/strong> loop, with an additional check for counting up or counting down, and if the bounds match the increment:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>   if ((start &lt; stop) &amp;&amp; (step &gt; 0)) {\n        for (int i = start; i &lt;= stop; i += step) {\n            printf(\"%d\\n\", i);\n        }\n    }\n    else if ((stop &lt; start) &amp;&amp; (step &lt; 0)) {\n        for (int i = start; i &gt;= stop; i += step) {\n            printf(\"%d\\n\", i);\n        }\n    }<\/code><\/pre>\n\n\n\n<p>We actually can make this program slightly smaller by incrementing the <strong>start<\/strong> variable, instead of a new counter variable. But the program isn&#8217;t that big to start with, and an extra integer variable makes the code easier to read without that much overhead. So let&#8217;s keep it simple and use this version.<\/p>\n\n\n\n<p>And that&#8217;s all we need to write our own program that prints a list of numbers. The two <strong>if<\/strong> statements at the end neatly ensure that the program can only count up if the bounds are correct and the step is positive, or count down if the step is negative. The program prints nothing otherwise, including if the user provided a zero step size.<\/p>\n\n\n\n<p>The full listing looks like this:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>#include &lt;stdio.h&gt;\n#include &lt;stdlib.h&gt;\n\n\nint main(int argc, char **argv)\n{\n    int start = 1, stop = 10, step = 1;\n\n\n    if (argc &gt; 1) {\n        start = atoi(argv&#91;1]);\n\n\n        if (argc &gt; 2) {\n            stop = atoi(argv&#91;2]);\n\n\n            if (argc &gt; 3) {\n                step = atoi(argv&#91;3]);\n\n\n                if (argc &gt; 4) {\n                    fputs(\"usage: num &#91; start &#91; stop &#91; step ]]]\\n\", stderr);\n                    fputs(\"extra options ignored\\n\", stderr);\n                }\n            }\n        }\n    }\n\n\n    if ((start &lt; stop) &amp;&amp; (step &gt; 0)) {\n        for (int i = start; i &lt;= stop; i += step) {\n            printf(\"%d\\n\", i);\n        }\n    }\n    else if ((stop &lt; start) &amp;&amp; (step &lt; 0)) {\n        for (int i = start; i &gt;= stop; i += step) {\n            printf(\"%d\\n\", i);\n        }\n    }\n\n\n    return 0;\n}<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Testing the program<\/h2>\n\n\n\n<p>Let&#8217;s try a few examples to see how the new program works. First, these commands should work as expected because they <em>count up<\/em> or <em>count down<\/em> within a range:<\/p>\n\n\n\n<p>Count from 5 to 10:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ .\/num 5\n5\n6\n7\n8\n9\n10<\/code><\/pre>\n\n\n\n<p>Count from 10 to 15:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ .\/num 10 15\n10\n11\n12\n13\n14\n15<\/code><\/pre>\n\n\n\n<p>Count from 2 to 10, by 2:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ .\/num 2 10 2\n2\n4\n6\n8\n10<\/code><\/pre>\n\n\n\n<p>Count <em>down<\/em> from 10 to 5:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ .\/num 10 5 -1\n10\n9\n8\n7\n6\n5<\/code><\/pre>\n\n\n\n<p>If the step is too large, not every number will be printed, and that&#8217;s okay:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ .\/num 1 10 100\n1<\/code><\/pre>\n\n\n\n<p>Valid start, stop and end values with leftover options also work, although the extra arguments have no effect and just print a warning:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ .\/num -1 1 1 x y z\nusage: num &#91; start &#91; stop &#91; step ]]]\nextra options ignored\n-1\n0\n1<\/code><\/pre>\n\n\n\n<p>However, we would expect <em>out of range<\/em> command lines to fail, because they are impossible to complete. The program prints nothing and immediately exits:<\/p>\n\n\n\n<p>Counting <em>up<\/em> from 10 to 5? Not possible.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ .\/num 10 5<\/code><\/pre>\n\n\n\n<p>Counting <em>down<\/em> from 5 to 10? Nothing to do.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ .\/num 5 10 -1<\/code><\/pre>\n\n\n\n<p>A <em>zero<\/em> increment? That won&#8217;t work either.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ .\/num 1 10 0<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Roll your own<\/h2>\n\n\n\n<p>Open source gives you the ability to change a system to meet your personal needs. And with a little programming, you have the power to make your own tools to replace or augment the commands on your system. This is a fairly straightforward example, but it&#8217;s a real-life case of where I&#8217;ve created a small command line tool to help me do things <em>the way I want<\/em>. That&#8217;s why I love working with open source systems, especially those that give you compilers and other resources to build new tools.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>I love working with open source systems, especially those that give you compilers and other resources to build new tools.<\/p>\n","protected":false},"author":33,"featured_media":3293,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_lmt_disableupdate":"","_lmt_disable":"","footnotes":""},"categories":[100,5,150],"tags":[104,91,152],"class_list":["post-14036","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-command-line","category-linux","category-programming","tag-command-line","tag-linux","tag-programming"],"modified_by":"Jim Hall","_links":{"self":[{"href":"https:\/\/www.both.org\/index.php?rest_route=\/wp\/v2\/posts\/14036","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=14036"}],"version-history":[{"count":4,"href":"https:\/\/www.both.org\/index.php?rest_route=\/wp\/v2\/posts\/14036\/revisions"}],"predecessor-version":[{"id":14043,"href":"https:\/\/www.both.org\/index.php?rest_route=\/wp\/v2\/posts\/14036\/revisions\/14043"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.both.org\/index.php?rest_route=\/wp\/v2\/media\/3293"}],"wp:attachment":[{"href":"https:\/\/www.both.org\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=14036"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.both.org\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=14036"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.both.org\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=14036"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}