This is an old revision of the document!


Obsolete and deprecated syntax

This (incomplete) page describes some syntax and commands considered obsolete by some measure. A through discussion of the rationale is beyond the scope of this page. See the portability page for a discussion on portability issues.

This first table lists syntax that is tolerated by Bash but has few if any legitimate uses. These features mostly exist for Bourne, csh, or some other backwards compatibility with obsolete shells, or were Bash-specific features considered failed experiments and deprecated or replaced with a better alternative. These should be irrelevant to most everyone except maybe code golfers. New scripts should never use them. Unless otherwise noted, items on this list are not specified by POSIX, and some may be incompatible with POSIX.

Syntax Replacement Description
Unquoted expansions, Word splitting, and Pathname expansion (globbing) Proper quoting, Ksh/Bash-style arrays, The "$@" expansion, The read builtin command Word-splitting is undoubtedly and by far the #1 source of bugs, security issues, and beginner mistakes in all of shell scripting. It is a misfeature reluctantly carried over into ksh (and consequently, POSIX) from the Bourne shell by David Korn due to complaints of broken scripts and changes in previously documented behavior. Most of the important expansions are performed at the same time from left to right. However, a few expansions, most notably word-splitting and globbing, and also in shells other than Bash, brace expansion, are performed on the results of previous expansions, by default, unless they are quoted. This means that the act of dereferencing a variable, depending on the value of the variable, can yield different results depending on possibly uncontrolled side-effects like the value of IFS, and the names of files in the current working directory. You can't get globbing without word-splitting, or vice versa (without set -f). You cannot store a command in a variable, and safely evaluate it by expanding it unquoted. If possible, always choose a shell with Korn-shell arrays such as Bash. They are a vital but non-standard feature for writing clean, safe scripts. Well-written scripts don't use word-splitting at all. A significant proportion of the issues on the famous Pitfalls list fall under this category. See also: http://mywiki.wooledge.org/DontReadLinesWithFor
&>FILE and >&FILE >FILE 2>&1 This redirection syntax is short for >FILE 2>&1 and originates in the C Shell. The latter form is especially uncommon and should never be used, and the explicit form using separate redirections should be preferred over both. These shortcuts contribute to confusion about the copy descriptor because the syntax is unclear. They also introduce parsing ambiguity and conflict with POSIX. Shells without this feature treat cmd1 &>file cmd2 as: "background cmd1 and then execute cmd2 with its stdout redirected to file", which is the correct interpretation of this expression. See redirection
$[EXPRESSION] $((EXPRESSION)) This undocumented syntax is completely replaced by the POSIX-conforming arithmetic expansion $((EXPRESSION)). See arithmetic expansion
`COMMANDS` $(COMMANDS) This is the older Bourne-compatible form of the command substitution. Both the `COMMANDS` and $(COMMANDS) syntaxes are specified by POSIX, but the latter is greatly preferred. See: http://mywiki.wooledge.org/BashFAQ/082
COMMAND |& COMMAND COMMAND 2>&1 | COMMAND This is an alternate pipeline operator derived from Zsh. Officially, it is not considered deprecated by Bash, but I highly discourage it. It conflicts with the list operator used for coprocess creation in most Korn shells. It also has confusing behavior. The stdout is redirected first like an ordinary pipe, while the stderr is actually redirected last – after other redirects preceding the pipe operator. Overall, it's pointless syntax bloat. Use an explicit redirect instead.
function NAME() COMPOUND-CMD NAME() COMPOUND-CMD or function NAME { CMDS; } This is an amalgamation between the Korn and POSIX style function definitions - using both the function keyword and parentheses. It has no useful purpose and no historical basis or reason to exist. It is not specified by POSIX. It is accepted by Bash, mksh, zsh, and perhaps some other Korn shells, where it is treated as identical to the POSIX-style function. It is not accepted by AT&T ksh. It should never be used. See the next table for the function keyword.
for x; { …;} do, done, in, esac, etc. This undocumented syntax replaces the do and done reserved words with braces. Many Korn shells support various permutations on this syntax for certain compound commands like for, case, and while. Which ones and certain details like whether a newline or semicolon are required vary. Only for works in Bash. Needless to say, don't use it.
set -e, set -o errexit, and the ERR trap proper control flow and error handling set -e causes non-zero exit statuses to be fatal. It is a legacy feature meant mainly for very simple batch scripts that contain a series of commands with little or no control flow statements (like conditionals). While the issue is somewhat controversial, this author recommends never using it. Anything that can be done with set -e can be done better using other constructs. Since non-zero exit statuses are a fundamental part of any non-trivial script, set -e follows many confusing, non-obvious rules which disable its effects in certain places. set -e is a poor means of error handling, and can even be dangerous, because it bypasses all normal control flow and exits the script fatally, in possibly unexpected places. It should especially never be used in init scripts. All of this also applies to the ERR trap, though I've seen it used in a few places in shells that lack pipefail or PIPESTATUS. The ERR trap is not POSIX, while set -e is. The set -e feature generates more questions and false bug reports on the Bash mailing list than all other features combined! Please do not use set -e or suggest it to others. If you still refuse to take this advice, make sure you understand exactly how it works. For more details, see: http://www.fvue.nl/wiki/Bash:_Error_handling
set -u Proper control flow and error handling set -u causes attempts to expand unset variables or parameters as fatal errors. Like set -e, it bypasses control flow and exits immediately from the current shell environment. Like non-zero statuses, unset variables are a normal part of most non-trivial shell scripts. It is not very useful even for error checking or debugging. See BashFAQ/083 for how to properly test for defined variables. Don't use set -u.
${var?msg} or ${var:?msg} Proper control flow and error handling Like set -u, this expansion throws a fatal error which immediately exits the current shell environment if the given parameter is unset (or unset or null). It prints the error message given to the right of the operator. If a value is expected and you'd like to create an assertion or throw errors, it is better to test for undefined variables using one of these techniques and handle the error manually, or call a die function. This expansion is defined by POSIX. It's better than set -u, because it's explicit, but not by much.

This table lists features that have some legitimate uses, such as for those with specific portability requirements, but are more frequently (mis)used for no reason. Writing portable scripts that use non-POSIX features requires detailed knowledge to account for many (sometimes undocumented) differences across many shells.

Syntax Replacement Description
function NAME { CMDS; } NAME() COMPOUND-CMD This is the ksh form of function definition created to extend the Bourne and POSIX form with modified behaviors and additional features like local variables. The idea was for new-style functions to be analogous to regular builtins with their own environment and scope, while POSIX-style functions are more like special builtins. function is supported by almost every ksh-derived shell including Bash and Zsh, but isn't specified by POSIX. Bash treats all function styles the same, but this is unusual. function has some preferable characteristics in many ksh variants, making it more portable for scripts that use non-POSIX extensions by some measures. If you're going to use the function keyword, it implies that you're either targeting Ksh specifically, or that you have detailed knowledge of how to compensate for differences across shells. It should always be consistently used with typeset, never declare or local. See shell function definitions
let 'EXPR' ((EXPR)) or [ $((EXPR)) -ne 0 ] let is the "simple command" variant of arithmetic evaluation command, which takes regular arguments. Both let and ((expr)) were present in ksh88, and everything that supports one should support the other. Neither are POSIX. The compound variant is preferable because it doesn't take regular arguments for wordsplitting and globbing, which makes it safer and clearer. It is also usually faster, especially in Bash, where compound commands are typically significantly faster. Some of the (few) reasons for using let are detailed on the let page. See arithmetic evaluation compound command
[ EXPRESSION ] and test EXPRESSION [[ EXPRESSION ]] The test and [ commands are the Bourne/POSIX test expression. It takes regular arguments, unlike the Ksh/Bash [[ command. While the issue is analagous to let vs ((, the advantages of [[ vs [ are even more important because the arguments/expansions aren't just concatenated into one expression. If at all possible, use the conditional expression ("new test command") [[ EXPRESSION ]]. Unless there is a need for POSIX compatibility, there are only a few reasons to use [.

See also

Discussion

Enter your comment. Wiki syntax is allowed: