Michael Eriksson
A Swede in Germany
Home » Software development | About me Impressum Contact Sitemap

Advantages of command line over GUI

Introduction

A common misconception is that the command line is a left-over from the age of dinosaurs, which has now been superseded by a superior GUI paradigm. This, however, is truly an error. Below, I will make some comparisons between a typical Bash-level command line and a Windows-level GUI setup.

Preliminary remarks

The term “GUI” covers a greater area than “command line”, and the two are in no way excluding each other. (Consider, by analogy, weight-training and shot-put.) This article focuses on what a command line can do, and why it is superior for these choices. The GUI paradigm has other strengths, which are not denied; however, a GUI should be used in those areas, not to replace things that were originally done with the command line—and that are still done better with the command line. As a result, the below deals mostly with command-line shellsw vs. graphical shells; however, other areas are touched upon.

An overlapping issue is where to draw the line between GUIs and other UIs, and between command lines and shells, what differences arise through a mostly point-and-click resp. a mostly keyboard driven interface, etc. For the purposes of this discussion, I gloss over such issues and consider e.g. an instance of Bash a command line, an instance of Vim started on that command line and running in the same window a GUI, and the intra-Vim functionality triggered by (per default) typing “:” in the normal mode a further (now internal) command line. To discuss the superior usability of Vim over MS Word, e.g., is off topic. (However, my focus is on GUIs in the style of e.g. MS Windows.)

From the POV of an application, there are two types of command-line support: Firstly, having an internal command line (as with e.g. Vim and many other tools in the Unix-tradition); secondly, providing sufficiently many command-line options and whatnot that the application can be controlled sufficiently well on an external command line, e.g. in Bash. Ideally, applications should have both—increasingly, they have neither.

A complication is that not every command line is equal in abilities or how these abilities are accessed:

For instance, that history is accessed with arrow keys (cf. below) is fairly standard (and below I will ignore other variations for simplicity); however, other variations are possible, be it as a complement (for instance, most Unix-style shells have a vi mode, where “j” and “k”, or some other key combinations, can be used for the same purpose) or as an outright “instead” (notably, in shells prior to the spread of keyboards with arrow keys). I will often silently assume a behavior similar to that of Bash; however, the principles behind the text would apply even if such details were altered.

For instance, some poorly made command lines, maybe added in a perfunctory manner by developers who do not understand command lines, can give a very incorrect impression of what command lines should be. A particular annoyance to me is the absurdly dumb command line of “Battle of Wesnoth”, which basically only has the ability to receive typed text—no history, no completion, no or only rudimentary editing, ... (The more the shame, as libraries like readline make it easy to add reasonable command-line functionality with little effort.) For the purposes of this text, I assume a command line that is “grown up”—just like I assume that a GUI is reasonably “grown up”.


Side-note:

However, I caution that future developments can affect the correctness of what is said below, which applied in reasonable detail in 2009 (original writing of this page) and in at least the big picture in 2023 (major overhaul), but (a) need not do so in 2037 or 2051, (b) might deviate in detail even in 2023. (For instance, I have had only minimal contact with Windows versions > 7. For this, I am very grateful, but it does limit my ability to update comparisons and whatnot to the world of 2023.)

An interesting change between 2009 and 2023 is the immense popularity of smartphones, where the advantages of command lines have been reduced by the (for now?) lesser ability to enter text relative a regular computer with a keyboard. Another, the popularity of voice control for at least some tasks (“Alexa! Order me a keyboard!”). Voice control is a sufficiently different approach that neither “GUI” nor “command line” applies; although, it could be used in conjunction with either.


Starting tasks

  1. A command line has an easily accessed history, where it is possible to go up and down with the arrow keys, search for previous entries (even using regular expressions), and edit previous commands before launch. Several old commands can be grouped and edited, or saved to a file for later re-use. (In fact, for e.g. Bash, the history is automatically stored in a file that can be manually edited at wish.)

    I have never seen a GUI that has truly supported these capabilities; although, an extremely rudimentary support through mechanisms in the “last ten launched applications” or “last ten opened files” families is common.


    Side-note:

    Windows does have “Run command” (a miniature, fake, command line) and the DOS-emulator (a weak and user-unfriendly, but true, command line). However, these belong to the command-line camp, and cannot be used in the current comparison. (They would, however, be relevant in a comparison Unix–Windows.) Note, however, that the do not deserve to be mentioned in the same sentence as the likes of Bash, Ksh, Zsh, ... For someone used to the old DOS-shell, the Windows-shell might indeed look like an improvement on all fronts.

    Windows PowerShellw, which I am not personally familiar with, is also a command line. That Microsoft capitulated after twenty years of command-line disparagement, and finally tried to provide a “real” command line, could actually be seen as a very strong argument for the superiority of command lines. Notably, no version of MS-DOS (be it as an OS or as an emulation) managed to reach the capabilities that Unix-shells already had in 1982 (the year MS-DOS was released) in the roughly twenty-five years until the release of PowerShell.


    Addendum:

    By 2023, I have had some minor professional contacts through one project, all involving scripting. Even in that project, however, I did not see anyone use PowerShell for anything but scripting. The closest to a use as a command line was to interactively try some statements before they were put in a script. No-one used it as an interactive replacement for Windows functionality in the way that a shell user in the Unix-verse would or, under Windows, someone using e.g. Cygwin to run a Unix-style shell.

    Whether this was a result of deficiencies in PowerShell or of prejudice against command lines among the colleagues, I leave unstated.



    Notably, the command-line history automatically includes all commands launched on it—many of which would occur within an application in a GUI centric environment. Each of these individual applications would need to provide a history. Consider a simple task like making a tricky multiplication with a “virtual calculator”: Enter “142536435” with the mouse on the virtual keys, enter “*”, enter “89735389”, enter “=”, realize that “142534435” was intended, start over again. In e.g. Bash, OTOH, expr 142536435 \* 89735389 can be entered with the keyboard; and when the error is seen, just recalling the command and changing one digit is enough.


    Side-note:

    Similarly, newer non-GUI calculators running in a terminal window usually have a fully functional command line. (And, no, command lines are by no means limited to shells.) With the almost excessive power of modern computers, I often go straight into R (!), even for (interactive) tasks that could be handled by expr or shell-internal arithmetic, let alone a regular calculator.


  2. If a command-line user wants to call a certain program several times with different parameters (e.g. to use several browser instances with different security settings, or to do a certain task on different files) he specifies the first group of parameters on the command line, recalls and edits the command, recalls and edits the command, ..., until all variations have been launched.

    (This, that is, unless he uses the power of the command line to get by in an even better manner, e.g. by a loop or “brace expansion” in Bash. Try something like “echo a{b,c,d}{01..12}” for a demonstration.)

    A GUI user finds the right entry in the application menus, launches the application, goes into the settings in the GUI and makes corresponding changes (e.g. JavaScript On/Off, cookies On/Off), goes into the application menus, ...

    Or does he? More likely than not, the application launched will refuse to be run in more than one simultaneous instance, or insist upon using common settings for all instances—meaning that he cannot do this concurrently at all... (Whether lack of concurrency is a problem will depend on the exact task at hand.)


    Side-note:

    Even by 2009, it had become increasingly more common to not provide command-line options that would have been included as a matter of course as late as the 1990s. By 2023, some developers do not seem to even understand the idea of having command-line options... This has the regrettable side-effect that the power of command lines is unnecessarily diminished.


  3. Similarly, the ability to specify options on the command line can make life a lot easier. Consider software DVD players: With e.g. Mplayerw (a command-line player) it is easily possible to specify options like language to use for subtitles and audio, volume, and similar, on the command line. A particular advantage is that by directly specifying the title and/or chapter to play, the unethical and customer-despising forced copyright-warnings can be skipped—as can overly long and time-wasting animated menus. In contrast, GUI players force the user to make such specifications in the GUI, which is a major PITA (considering the lack of respect for default settings in the DVD industry). Worse yet, the poor user is often forced to use the DVD-internal menus, which are typically absolutely inexcusable. Contrast Mplayer with the absurdity Kaffeinew or one of the typical commercial players for Windows.

  4. A command line makes it easy to call several commands at the same time, make execution of one command conditional on the success of another, and to use the concept of a pipew—one of the greatest usability helpers there is.

    I have never seen a GUI with anything similar.

  5. Often a command line provides powerful programmatic abilities (“scripting”) fully comparable to a programming language, but usable with very little effort.

    A GUI would typically require the writing and compilation of a full blown program for the same effect. (However, Windows does have some GUI-scripting abilities.) In any case, this requires leaving the Windows-shell to use a specific application to write the program/script/whatnot.

Use of input/output from one application with another

On the command line this is trivial, by use of the aforementioned “pipe” concept and the ability to print output on several different output-/input-streams that can be redirected to/from files and applications.

The typical set of GUI applications will require either manual copy-and-paste operations or the manual saving and reading to/from files.

Example: Assume that we have three applications that respectively download the contents of an URL, convert a HTML page to plain-text, and count the number of words in a plain-text page. Assume further that we have want to find out the number of words on a certain webpage. In case of GUI applications we have to

  1. Start application one. Download the webpage. Possibly explicitly save the webpage to a specific name (many download tools save to a file automatically). Close application one.

  2. Start application two. Open the right file. Convert the file. Save the file. Close application two.

  3. Start application three. Open the right file. Read the output. Close application two.


Side-note:

In e.g. Windows the likelier approach would be to find the file and start an application on that file, rather than starting an application and then opening the file in it. In most cases, however, the amount of work will be the same, or even higher, this way, because only the most popular applications tend to be found in the “open with” short-lists.


On a command line, app1 <URL> | app2 | app3 will readily provide the answer.


Addendum:

Of course, for such easy tasks, Linux comes with corresponding applications. For instance

wget -q -O - https://www.aSwedeInGermany.de/50SoftwareDevelopment/50ShellVsGUI.html|html2text|wc -w

gives the above count for this page it self.

The calls contain a few flags and options. Of these only -O - is necessary: wget per default writes to a file and this addition forces output into the pipe instead. The -q just suppresses some “diagnostic” information that makes the end result harder to read, but which does not affect the count. The -w for wc restricts the count to words, where per default counts for words, lines, and characters would have been provided.

However, note that there are often matters of definition, personal preferences, and similar involved (regardless of approach) that can lead to differences in outcome between different solutions. For instance, when converting to text, should or should not alt-texts for images be included?


Reuse of existing tools vs. re-inventing the wheel

An understandable reaction to the above example would be that these three functions should be provided by one single tool—as it might well be in a command-line context too.

In many cases, this will make sense; in many others it will not. Above it could make sense to have a feature of a web browser that simple tells the user how many words are present in the page he watches; however, it will not generally be possible to predict or correctly implement every conceivable weird thing that the user might want to do—nor will it be viable to implement each wish for each application, each document format, etc. For instance, if we assume a three-step pipe and just ten calls that make sense in each step, we have a thousand combinations (10^3)—should we write a separate program for each or rely on combinations of tools? (And, of course, a pipe can have virtually any length and include virtually any number of programs.)

Here a command line brings great advantages: Existing small tools can easily be combined in a variety of ways to give even a semi-proficient user almost any piece of functionality that he wants. The same is not true, even by a long chalk, for GUI applications. (There are some attempts to gather very common functionality, e.g. spell checkers, in generic plug-ins, and to provide plug ins tailored to frameworks like Eclipse for popular tools; however, these are very far from having sufficient generality at this point of time—and they are mainly intended for application developers, not end users.)

Consider e.g. changing the above requirement to count all unique words: Only very rarely will a GUI tool bring this functionality; on the command line, it suffices to change the last application in the pipeline (or precede it with an extra filter, so that the last application is feed a unique list to count).


Addendum:

(Due to a problem with the self-made template language for this website, I represent a “\” immediately followed by an “n” as “\ n” below. If someone wants to try the below code, a manual correction is necessary. TODO fix template language.)

In line with the above addendum, a code snippet that does this to some approximation:

wget -q -O - https://www.aSwedeInGermany.de/50SoftwareDevelopment/50ShellVsGUI.html|html2text| sed -e ’s/[^[:alpha:]]\+/ /g’ -e ’s/ /\ n/g’ |tr ’[:upper:]’ ’[:lower:]’|sort|uniq |wc -w

The approximation largely arises through questions like whether “shell” and “shells” should count as one or two unique words, how digits should be handled, and similar. These are question unrelated to e.g. command line vs. GUI, however. Some fine-tuning is possible: For instance, chances are that an empty line would count as a word, as the statement is currently written. The fix is not hard, but I prefer the above, as it is an almost-off-the-top-of-my-head solution, which is suitable for a quick throw-away expression and well illustrates how much can be achieved fast. (Fully-off-the-top-of-my-head, I used expressions like “a-z” over character classes like “[:lower:]”, which would have worked just as well in most cases, but is less safe in an international context and is considered poor style. To correct this, I had to perform a brief lookup of the correct names and syntax.)


A more advanced example: What kind of renamings, moves, deletions, searches, etc. should a user be able to do where files are concerned? Here there are basically three schools (the names are just informal hints):

  1. The Windows school proposes that the user is given access to the barest minimum that can be used without rendering the system useless.

  2. The Midnight Commander school proposes that as many use cases as possible should be thought through and implemented.

  3. The Bash school proposes that the user should be given strong basic abilities and be enabled to extend and combine these on his own with ease.

The Bash school will win by several horse-lengths, at least when focus is on accomplished users. Just to give one example: What file manager provides the ability to find all files in the current directory that begin with an “A” and has a third letter that is not “c” (a name length of at least three letters assumed) and rename them to the old name concatenated with the first line of the file (files assumed to not be empty)?

Try the following Bash snippet:

for file in A?[^c]* do suffix="$(head -1 "$file")"; mv "$file" "$file$suffix"; done

(No fear: This is actually relatively straight-forward for the proficient user—normally, I would even have condensed the two lines in the loop and skipped the suffix variable. It does, however, contain an extra assumption of no sub-directories being present. If needed, this can be corrected, e.g. by using find or test.)


Side-note:

Why would anyone want to do that? Why should I take such weird wishes into consideration when I write an application?

Frankly, what the user wants or do not wants is not for you to decide—he might very well have a valid reason to do this. (Also see below for a later, real-life, example.) The fact that so many modern companies (above all, Microsoft) presume to decide the exact extent of what should be possible with their applications, is one of the greatest problems with modern software. A good software enables the user to do whatever he wants to; it does not restrict him. (Of course, here is where a good command line and/or a good scripting language shines: by giving some basic flexible abilities, there is no need to provide a “pre-assembled” solution for all conceivable problems—Bash over Midnight Commander over Windows.)

Providing extra little nice-to-haves, like the word count above in a browser, is quite in order; making an application hard to use with other applications out of a short-sighted view on what users might want to do is not. Just adding the ability to read from stdinw and write to stdoutw and to activate a certain (already built-in) conversion from the command line, can make a world of difference.



Addendum:

A few months after writing the above, I found myself with the need to identify which several files with the ending “.html” did not have an empty third line—a use case that I had certainly not foreseen, myself.

I used the following:

for file in $(find -name "*.html") do echo -n "$file:" sed -n ’3p’ $file done|grep -v ": *$"

Note that this assumes that no third line ended with a “:” and that all files were at least three lines long—of which I was certain.


Side-note:

More generally, such ad-hoc code is often a little sloppy. For instance, in addition to the previous paragraph, it is wasteful of me to not quit the sed statement after the third line—but who cares when the statement is only used once? For instance, I should have escaped the $file in the same line, but I try to keep my filenames free of nonsense like spaces and if I know that none of the files at hand are tricky in this regard, I can afford the sloppiness. For code intended for re-use, use by others, use in “unknown territory”, whatnot, greater attention to detail can be needed. (Similar remarks can apply elsewhere on this page.)



Batching and automatization

A GUI is inherently interactive, and attempting to do things without interaction, to bind several things to one command, to launch an application (or a set of applications) for a certain task at a certain time, etc., is very hard. Even with tools and scripts that have the capability of simulating user interaction, this is error prone at best: There simply is no reliable way to do things like this in today’s GUI environments. On the command-line, OTOH, it is trivial—in fact, the greatest potential complication is that “modern” applications have been written without command-line support, which unnecessarily weakens the command line.

Miscellaneous

Generally, a GUI tends to restrict the user, and a command line to enable the user. Consider, e.g. the ability to use tab completion, aliases, own shell-scripts, and similar, in Bash; and contrast them with the rudimentary (or entirely absent) correspondents under Windows. A thorough discussion of all such abilities would make this article at least twice as long as it already is.

Advantages for beginners

A GUI can bring large advantages for beginners and very casual users. This is laudable, and should be encouraged; however, it must not be used as an excuse to limit the users who actually want to move on. Any organisation that is content with its interface when raw beginners can use it, should be condemned: A truly good UI, be it graphical or not, should make ease of use greater for everyone—not just beginners. (And, trust me, e.g. Windows, Word, Lotus Notes, ..., are absolutely abhorrent for a true power-user—user-unfriendly, limiting, frustrating, even sometimes sabotaging.)