Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems. It's 100% free, no registration required.

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

This may be a stupid question but I'm fairly new to bash scripting and have found multiple examples of "esac" appearing at the end of a bash case statement but I have not found any clear documentation on it's use. The man page uses it, and even has an index on the word (https://www.gnu.org/software/bash/manual/bashref.html#index-esac), but does not define it's use. Is it the required way to end a case statement, best practice, or pure technique?

share|improve this question
The index entry for esac points exactly where it should — to the line that defines it and illustrates that it's required. – hobbs Jan 19 at 13:52
@hobbs, you are correct that the index points to the line that illustrates its use but it does not define it in any way, especially compared to the way it describes the use of other characters like "|" or ";" or ";;". Now that I've read the answer(s), the backwards spelling "case" appears to be such a de facto standard for ending commands that most experienced users would take it for granted. – GrnMtnBuckeye Jan 20 at 15:31
If you didn't have esac or something like it, how do you think it would be able to tell where the end of the case statement is? – Barmar Jan 20 at 20:36
It defines it as being part of the syntax of the case statement, in the same way that else, elif, and fi are defined as being part of the syntax of an if statement. It doesn't have any semantics of its own, so there isn't anything to say about it, but it's at the end of the definition of a case statement, so it's where a case statement ends. The fact that it's case spelled backwards is a convenient curiosity, but the computer doesn't care, it just knows that it's looking for a certain word. – hobbs Jan 20 at 20:37
up vote 40 down vote accepted

Like fi for if and done for for, esac is the required way to end a case statement.

esac is case spelled backward, rather like fi is if spelled backward. I don't know why the token ending a for block is not rof.

share|improve this answer
You mean why isn't it od to end a do block? :) – Wildcard Jan 18 at 22:37
Imagine having to type \od every time you wanted to use that utility! Which is rare, but my point stands ;) – Score_Under Jan 18 at 23:20
Pulled you off of 666. You're welcome :P. And great answer! – Zacharee1 Jan 19 at 1:17
@Wildcard It's fi and not neht, so by analogy it would be rof (or elihw) and not od (also, of course, od is already taken) ... but maybe this is expecting too much self-consistency out of one of the most self-inconsistent languages there is. – zwol Jan 19 at 16:11
ROTFL nothing else to say – gerhard d. Jan 20 at 15:50

The esac keyword is indeed a required delimiter to end a case statement in bash and most shells used on Unix/Linux excluding the csh family.

The original Bourne shell was created by Steve Bourne who previously worked on ALGOL68. This language invented this reversed word technique to delimit blocks.




The latter is not do/od but do/done in Bourne and all the derived shells including bash because od was already existing as a Unix command since its inception (octal dump).

Note that do/done functional blocks are introduced by either the for, the while, or the until instructions. for, while and until do not need to be terminated as do is sufficient. That's the reason why there is no need for the hypothetical rof and elihw tokens.

share|improve this answer

The "esac" terminates an earlier "case" to form a "code-block".

In Algol68 they are used, generally the reversed character sequence of the introducing keyword is used for terminating the enclosure, e.g. ( if ~ then ~ else ~ fi, case ~ in ~ out ~ esac, for ~ while ~ do ~ od ).

I would call them "Guarded Blocks" after Edsger Dijkstra and his Guarded Command Language.

od presumably was not used in the Bourne Shell because of the pre-existence of the Unix "od" command.

The history:

The "Guarded Block" idea appear to have come from ALGOL 68 e.g. English:

proc days in month = (int year, month)int:

  case month in
    if year mod 4=0 ∧ year mod 100≠0  ∨  year mod 400=0 then 29 else 28 fi,
    31, 30, 31, 30, 31, 31, 30, 31, 30, 31

The Soviet's Algol68 LGU implementation did the same: In English Algol68's reverent case statement reads case ~ in ~ out ~ esac, in Cyrillic this reads выб ~ в ~ либо ~ быв.

Then in 1975 Algol68's code-blocks were borrowed by Edsger Dijkstra for his Guarded Command Language. e.g.

if a ≥ b → max := a
| b ≥ a → max := b

Presumably Dijstra used "Guarded Blocks" to overcome the Dangling else ambiguity implemented in Algol60 and then re-engineered in the C Programming Language. (cf. shift-reduce conflict.)

Finally - from Algol68 - "esac" made it into the 1977 Bourne shell (where you discovered esac) courtesy of Stephen R. Bourne who had developed an early Algol68 compiler called ALGOL 68C.

Famously Stephen also used these same Guarded Blocks in a "C header file" called macro.h

#define IF  if(
#define THEN    ){
#define ELSE    } else {
#define ELIF    } else if (
#define FI  ;}

The notable software geniuses Landon Curt Noll and Larry Bassel stumbled upon Steve's macro.h code in 1984 while employed at National Semiconductor's Genix porting group and struggled to understand its application. And so Landon & Larry then created the International Obfuscated C Code Contest...

From 1984 until today there have been several thousand other "better" programming languages that do not use Dijkstra's Guarded Commands. And Steven Bourne's use of them in macro.h is now often cited in the "Software Development Dissertations" of IT undergraduates as proof they were not sleep in lectures. :-)

share|improve this answer
What's case out? never seen that syntax – Dani_l Jan 23 at 6:04
@Dani_l That's Algol68 syntax not adopted by the bourne shell. – jlliagre Jan 23 at 6:55
Thanks for the info – Dani_l Jan 23 at 7:09

Yes, it's required. As Jacob points out above, the logic of it is the same as if/fi. Traditional C comment delimiters /* and */ also pair similarly. Because C was written so that Unix could be written mostly in C, with the minimum of assembly code, with a large overlap between the C and Unix development teams, it's reasonable to assume a common source of the notion that the closing equivalent of a multi-character block delimiter should be the same sequence of characters in reverse order.

In contrast, loops like for, while, and until use do...done instead of reversing character order, so there is some inconsistency.

share|improve this answer
Syntax came from Bourne, which again was inspired by ALGOL. – Sukminder Jan 18 at 22:32

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.