difference between "function foo() {}" and "foo() {}"

I can define bash functions using or omitting the function keyword. Is there any difference?

#!/bin/bash

function foo() {
  echo "foo"
}

bar() {
  echo "bar"
}

foo

bar

Both calls to functions foo and bar succeed and I can’t see any difference. So I am wondering if it is just to improve readability, or there is something that I am missing…

BTW in other shells like dash (/bin/sh is symlinked to dash in debian/ubuntu) it fails when using the function keyword.

There is no difference AFAIK, other than the fact that the second version is more portable.

Answered By: schaiba

Semantically, those two forms are equivalent in Bash.

From the man page:

Shell functions are declared as follows:

name () compound-command [redirection]
function name [()] compound-command [redirection]

This defines a function named name. The reserved word function is optional. If the function reserved word is supplied, the parentheses are optional.

EDIT: I just noticed that this question is tagged posix. In POSIX sh, the function keyword is not used (though it is reserved).

Answered By: depquid

The reason there are two different syntaxes is historical. The function keyword came from ksh. The C-inspired () syntax came from the Bourne shell. POSIX standardizes only the Bourne foo () syntax. Bash and zsh support both, as well as the hybrid function foo () { … }. Except in ATT ksh, the resulting function is exactly the same.

Beware of a gotcha with the () syntax: the function name is subject to alias expansion.

alias f=g
f () { echo foo; }
type f               # f is an alias for g
type g               # g is a shell function
f                    # alias f → function g → print foo
f                   # no alias lookup → f: not found
g                    # function g

In ATT ksh (but not pdksh and its descendants such as mksh), there are a few differences between functions defined by function and functions defined with the Bourne/POSIX syntax. In functions defined by function, the typeset keyword declares a local variable: once the function exits, the value of the variable is reset to what it was before entering the function. With the classic syntax, variables have a global scope whether you use typeset or not.

$ ksh -c 'a=global; f () { typeset a=local; }; f; echo $a'
local
$ ksh -c 'a=global; function f { typeset a=local; }; f; echo $a'
global

Another difference in ksh is that functions defined with the function keyword have their own trap context. Traps defined outside the function are ignored while executing the function, and fatal errors inside the function exit only the function and not from the whole script. Also, $0 is the function name in a function defined by function but the script name in a function defined with ().

Pdksh does not emulate ATT ksh. In pdksh, typeset creates locally-scoped variables regardless of the function, and there are no local traps (though using function does make some minor differences — see the man page for details).

Bash and zsh introduced the function keyword for compatibility with ksh. However in these shells function foo { … } and foo () { … } are strictly identical, as is the bash and zsh extension function foo () { … } (except for potential alias expansion when parsing the definition, as explained above). The typeset keyword always declares local variables (except with -g of course), and traps are not local (you can get local traps in zsh by setting the local_traps option).

foo() any-command

is the Bourne syntax supported by any Bourne-like shell but bash, yash and recent versions of posh (which only support compound commands). (the Bourne shell and AT&T implementations of ksh don’t support foo() any-command > redirections unless any-command is a compound command though).

foo() any-compound-command

(examples of compound commands: { cmd; }, for i do echo "$i"; done, (cmd)… the most commonly used being { ...; })

is the POSIX syntax supported by any Bourne-like shell and the one you generally want to use.

function foo { ...; }

is the Korn shell syntax, which predates the Bourne syntax. Only use this one if writing specifically for the AT&T implementation of the Korn shell and need the specific treatment it receives there. That syntax is not POSIX, but is supported by bash, yash and zsh for compatibility with the Korn shell though those shells (and the pdksh-based variants of the Korn shell) don’t treat it any different from the standard syntax.

function foo () { ...; }

is the syntax of no shell and should not be used. It only happens to be supported by accident by bash, yash, zsh and the pdksh based variants of the Korn shell. Incidentally, it’s also the awk function syntax.

If we continue going down the esoteric list,

function foo() other-compound-command

(like function foo() (subshell) or function foo() for i do; ... done) is even worse. It is supported by bash, yash and zsh, but not ksh, even the pdksh-based variants.

While:

function foo() simple command

is only supported by zsh.

foo bar() any-command

Or even:

$function_list() any-command

To define several functions at once is only supported by zsh

function { body; } args
() any-compound-command args

Which are anonymous function invocations, are only supported by zsh as well.

Answered By: Stéphane Chazelas

Several others have answered correctly by now, but here’s my concise synopsis:

The second version is portable and is likely to work with many standard (particularly POSIX) shells.

The first version will work with only bash, but you may omit the parentheses following the function name with it.

Otherwise, they represent identical entities after bash interprets them.

Answered By: Dennis Estenson

If no one else has stated it already, the form function foo() {}, is invalid in Korn Shell (at least in KSH 93). The correct format is function foo {}, without the double parentheses. Either format is valid in BaSH and ZSH, while ASH (and by extension DASH) does not allow function keyword at all.

Answered By: Vinny
Categories: Answers Tags: , , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.