Compatibility with previous versions ==================================== This document details the incompatibilities between this version of bash, bash-5.2, and the previous widely-available versions, bash-3.2 (which is still the `standard' version for Mac OS X), 4.2/4.3 (which are still standard on a few Linux distributions), and bash-4.4/bash-5.0/bash-5.1, the current widely-available versions. These were discovered by users of bash-2.x through 5.x, so this list is not comprehensive. Some of these incompatibilities occur between the current version and versions 2.0 and above. 1. Bash uses a new quoting syntax, $"...", to do locale-specific string translation. Users who have relied on the (undocumented) behavior of bash-1.14 will have to change their scripts. For instance, if you are doing something like this to get the value of a variable whose name is the value of a second variable: eval var2=$"$var1" you will have to change to a different syntax. This capability is directly supported by bash-2.0: var2=${!var1} This alternate syntax will work portably between bash-1.14 and bash-2.0: eval var2=\$${var1} 2. One of the bugs fixed in the YACC grammar tightens up the rules concerning group commands ( {...} ). The `list' that composes the body of the group command must be terminated by a newline or semicolon. That's because the braces are reserved words, and are recognized as such only when a reserved word is legal. This means that while bash-1.14 accepted shell function definitions like this: foo() { : } bash-2.0 requires this: foo() { :; } This is also an issue for commands like this: mkdir dir || { echo 'could not mkdir' ; exit 1; } The syntax required by bash-2.0 is also accepted by bash-1.14. 3. The options to `bind' have changed to make them more consistent with the rest of the bash builtins. If you are using `bind -d' to list the readline key bindings in a form that can be re-read, use `bind -p' instead. If you were using `bind -v' to list the key bindings, use `bind -P' instead. 4. The `long' invocation options must now be prefixed by `--' instead of `-'. (The old form is still accepted, for the time being.) 5. There was a bug in the version of readline distributed with bash-1.14 that caused it to write badly-formatted key bindings when using `bind -d'. The only key sequences that were affected are C-\ (which should appear as \C-\\ in a key binding) and C-" (which should appear as \C-\"). If these key sequences appear in your inputrc, as, for example, "\C-\": self-insert they will need to be changed to something like the following: "\C-\\": self-insert 6. A number of people complained about having to use ESC to terminate an incremental search, and asked for an alternate mechanism. Bash-2.03 uses the value of the settable readline variable `isearch-terminators' to decide which characters should terminate an incremental search. If that variable has not been set, ESC and Control-J will terminate a search. 7. Some variables have been removed: MAIL_WARNING, notify, history_control, command_oriented_history, glob_dot_filenames, allow_null_glob_expansion, nolinks, hostname_completion_file, noclobber, no_exit_on_failed_exec, and cdable_vars. Most of them are now implemented with the new `shopt' builtin; others were already implemented by `set'. Here is a list of correspondences: MAIL_WARNING shopt mailwarn notify set -o notify history_control HISTCONTROL command_oriented_history shopt cmdhist glob_dot_filenames shopt dotglob allow_null_glob_expansion shopt nullglob nolinks set -o physical hostname_completion_file HOSTFILE noclobber set -o noclobber no_exit_on_failed_exec shopt execfail cdable_vars shopt cdable_vars 8. `ulimit' now sets both hard and soft limits and reports the soft limit by default (when neither -H nor -S is specified). This is compatible with versions of sh and ksh that implement `ulimit'. The bash-1.14 behavior of, for example, ulimit -c 0 can be obtained with ulimit -S -c 0 It may be useful to define an alias: alias ulimit="ulimit -S" 9. Bash-2.01 uses a new quoting syntax, $'...' to do ANSI-C string translation. Backslash-escaped characters in ... are expanded and replaced as specified by the ANSI C standard. 10. The sourcing of startup files has changed somewhat. This is explained more completely in the INVOCATION section of the manual page. A non-interactive shell not named `sh' and not in posix mode reads and executes commands from the file named by $BASH_ENV. A non-interactive shell started by `su' and not in posix mode will read startup files. No other non-interactive shells read any startup files. An interactive shell started in posix mode reads and executes commands from the file named by $ENV. 11. The <> redirection operator was changed to conform to the POSIX.2 spec. In the absence of any file descriptor specification preceding the `<>', file descriptor 0 is used. In bash-1.14, this was the behavior only when in POSIX mode. The bash-1.14 behavior may be obtained with <>filename 1>&0 12. The `alias' builtin now checks for invalid options and takes a `-p' option to display output in POSIX mode. If you have old aliases beginning with `-' or `+', you will have to add the `--' to the alias command that declares them: alias -x='chmod a-x' --> alias -- -x='chmod a-x' 13. The behavior of range specificiers within bracket matching expressions in the pattern matcher (e.g., [A-Z]) depends on the current locale, specifically the value of the LC_COLLATE environment variable. Setting this variable to C or POSIX will result in the traditional ASCII behavior for range comparisons. If the locale is set to something else, e.g., en_US (specified by the LANG or LC_ALL variables), collation order is locale-dependent. For example, the en_US locale sorts the upper and lower case letters like this: AaBb...Zz so a range specification like [A-Z] will match every letter except `z'. Other locales collate like aAbBcC...zZ which means that [A-Z] matches every letter except `a'. The portable way to specify upper case letters is [:upper:] instead of A-Z; lower case may be specified as [:lower:] instead of a-z. Look at the manual pages for setlocale(3), strcoll(3), and, if it is present, locale(1). You can find your current locale information by running locale(1): caleb.ins.cwru.edu(2)$ locale LANG=en_US LC_CTYPE="en_US" LC_NUMERIC="en_US" LC_TIME="en_US" LC_COLLATE="en_US" LC_MONETARY="en_US" LC_MESSAGES="en_US" LC_ALL=en_US My advice is to put export LC_COLLATE=C into /etc/profile and inspect any shell scripts run from cron for constructs like [A-Z]. This will prevent things like rm [A-Z]* from removing every file in the current directory except those beginning with `z' and still allow individual users to change the collation order. Users may put the above command into their own profiles as well, of course. 14. Bash versions up to 1.14.7 included an undocumented `-l' operator to the `test/[' builtin. It was a unary operator that expanded to the length of its string argument. This let you do things like test -l $variable -lt 20 for example. This was included for backwards compatibility with old versions of the Bourne shell, which did not provide an easy way to obtain the length of the value of a shell variable. This operator is not part of the POSIX standard, because one can (and should) use ${#variable} to get the length of a variable's value. Bash-2.x does not support it. 15. Bash no longer auto-exports the HOME, PATH, SHELL, TERM, HOSTNAME, HOSTTYPE, MACHTYPE, or OSTYPE variables. If they appear in the initial environment, the export attribute will be set, but if bash provides a default value, they will remain local to the current shell. 16. Bash no longer initializes the FUNCNAME, GROUPS, or DIRSTACK variables to have special behavior if they appear in the initial environment. 17. Bash no longer removes the export attribute from the SSH_CLIENT or SSH2_CLIENT variables, and no longer attempts to discover whether or not it has been invoked by sshd in order to run the startup files. 18. Bash no longer requires that the body of a function be a group command; any compound command is accepted. 19. As of bash-3.0, the pattern substitution operators no longer perform quote removal on the pattern before attempting the match. This is the way the pattern removal functions behave, and is more consistent. 20. After bash-3.0 was released, I reimplemented tilde expansion, incorporating it into the mainline word expansion code. This fixes the bug that caused the results of tilde expansion to be re-expanded. There is one incompatibility: a ${paramOPword} expansion within double quotes will not perform tilde expansion on WORD. This is consistent with the other expansions, and what POSIX specifies. 21. A number of variables have the integer attribute by default, so the += assignment operator returns expected results: RANDOM, LINENO, MAILCHECK, HISTCMD, OPTIND. 22. Bash-3.x is much stricter about $LINENO correctly reflecting the line number in a script; assignments to LINENO have little effect. 23. By default, readline binds the terminal special characters to their readline equivalents. As of bash-3.1/readline-5.1, this is optional and controlled by the bind-tty-special-chars readline variable. 24. The \W prompt string expansion abbreviates $HOME as `~'. The previous behavior is available with ${PWD##/*/}. 25. The arithmetic exponentiation operator is right-associative as of bash-3.1. 26. The rules concerning valid alias names are stricter, as per POSIX.2. 27. The Readline key binding functions now obey the convert-meta setting active when the binding takes place, as the dispatch code does when characters are read and processed. 28. The historical behavior of `trap' reverting signal disposition to the original handling in the absence of a valid first argument is implemented only if the first argument is a valid signal number. 29. In versions of bash after 3.1, the ${parameter//pattern/replacement} expansion does not interpret `%' or `#' specially. Those anchors don't have any real meaning when replacing every match. 30. Beginning with bash-3.1, the combination of posix mode and enabling the `xpg_echo' option causes echo to ignore all options, not looking for `-n' 31. Beginning with bash-3.2, bash follows the Bourne-shell-style (and POSIX- style) rules for parsing the contents of old-style backquoted command substitutions. Previous versions of bash attempted to recursively parse embedded quoted strings and shell constructs; bash-3.2 uses strict POSIX rules to find the closing backquote and simply passes the contents of the command substitution to a subshell for parsing and execution. 32. Beginning with bash-3.2, bash uses access(2) when executing primaries for the test builtin and the [[ compound command, rather than looking at the file permission bits obtained with stat(2). This obeys restrictions of the file system (e.g., read-only or noexec mounts) not available via stat. 33. Bash-3.2 adopts the convention used by other string and pattern matching operators for the `[[' compound command, and matches any quoted portion of the right-hand-side argument to the =~ operator as a string rather than a regular expression. 34. Bash-4.0 allows the behavior in the previous item to be modified using the notion of a shell `compatibility level'. If the compat31 shopt option is set, quoting the pattern has no special effect. 35. Bash-3.2 (patched) and Bash-4.0 fix a bug that leaves the shell in an inconsistent internal state following an assignment error. One of the changes means that compound commands or { ... } grouping commands are aborted under some circumstances in which they previously were not. This is what Posix specifies. 36. Bash-4.0 now allows process substitution constructs to pass unchanged through brace expansion, so any expansion of the contents will have to be separately specified, and each process substitution will have to be separately entered. 37. Bash-4.0 now allows SIGCHLD to interrupt the wait builtin, as Posix specifies, so the SIGCHLD trap is no longer always invoked once per exiting child if you are using `wait' to wait for all children. As of bash-4.2, this is the status quo only when in posix mode. 38. Since bash-4.0 now follows Posix rules for finding the closing delimiter of a $() command substitution, it will not behave as previous versions did, but will catch more syntax and parsing errors before spawning a subshell to evaluate the command substitution. 39. The programmable completion code uses the same set of delimiting characters as readline when breaking the command line into words, rather than the set of shell metacharacters, so programmable completion and readline should be more consistent. 40. When the read builtin times out, it attempts to assign any input read to specified variables, which also causes variables to be set to the empty string if there is not enough input. Previous versions discarded the characters read. 41. Beginning with bash-4.0, when one of the commands in a pipeline is killed by a SIGINT while executing a command list, the shell acts as if it received the interrupt. This can be disabled by setting the compat31 or compat32 shell options. 42. Bash-4.0 changes the handling of the set -e option so that the shell exits if a pipeline fails (and not just if the last command in the failing pipeline is a simple command). This is not as Posix specifies. There is work underway to update this portion of the standard; the bash-4.0 behavior attempts to capture the consensus at the time of release. 43. Bash-4.0 fixes a Posix mode bug that caused the . (source) builtin to search the current directory for its filename argument, even if "." is not in $PATH. Posix says that the shell shouldn't look in $PWD in this case. 44. Bash-4.1 uses the current locale when comparing strings using the < and > operators to the `[[' command. This can be reverted to the previous behavior (ASCII collating and strcmp(3)) by setting one of the `compatNN' shopt options, where NN is less than 41. 45. Bash-4.1 conforms to the current Posix specification for `set -u': expansions of $@ and $* when there are no positional parameters do not cause the shell to exit. 46. Bash-4.1 implements the current Posix specification for `set -e' and exits when any command fails, not just a simple command or pipeline. 47. Command substitutions now remove the caller's trap strings when trap is run to set a new trap in the subshell. Previous to bash-4.2, the old trap strings persisted even though the actual signal handlers were reset. 48. When in Posix mode, a single quote is not treated specially in a double-quoted ${...} expansion, unless the expansion operator is # or % or the new `//', `^', or `,' expansions. In particular, it does not define a new quoting context. This is from Posix interpretation 221. 49. Posix mode shells no longer exit if a variable assignment error occurs with an assignment preceding a command that is not a special builtin. 50. Bash-4.2 attempts to preserve what the user typed when performing word completion, instead of, for instance, expanding shell variable references to their value. 51. When in Posix mode, bash-4.2 exits if the filename supplied as an argument to `.' is not found and the shell is not interactive. 52. When compiled for strict Posix compatibility, bash-4.3 does not enable history expansion by default in interactive shells, since it results in a non-conforming environment. 53. Bash-4.3 runs the replacement string in the pattern substitution word expansion through quote removal. The code already treats quote characters in the replacement string as special; if it treats them as special, then quote removal should remove them. 54. Bash-4.4 no longer considers a reference to ${a[@]} or ${a[*]}, where `a' is an array without any elements set, to be a reference to an unset variable. This means that such a reference will not cause the shell to exit when the `-u' option is enabled. 55. Bash-4.4 allows double quotes to quote the history expansion character (!) when in Posix mode, since Posix specifies the effects of double quotes. 56. Bash-4.4 does not inherit $PS4 from the environment if running as root. 57. Bash-4.4 doesn't allow a `break' or `continue' in a function to affect loop execution in the calling context. 58. Bash-4.4 no longer expands tildes in $PATH elements when in Posix mode. 59. Bash-4.4 does not attempt to perform a compound array assignment if an argument to `declare' or a similar builtin expands to a word that looks like a compound array assignment (e.g. declare w=$x where x='(foo)'). 60. Bash-5.0 only sets up BASH_ARGV and BASH_ARGC at startup if extended debugging mode is active. The old behavior of unconditionally setting BASH_ARGC and BASH_ARGV is available at compatibility levels less than or equal to 44. 61. Bash-5.0 doesn't allow a `break' or `continue' in a subshell to attempt to break or continue loop execution inherited from the calling context. 62. Bash-5.0 doesn't allow variable assignments preceding builtins like export and readonly to modify variables with the same name in preceding contexts (including the global context) unless the shell is in posix mode, since export and readonly are special builtins. 63. Bash-5.1 changes the way posix-mode shells handle assignment statements preceding shell function calls. Previous versions of POSIX specified that such assignments would persist after the function returned; subsequent versions of the standard removed that requirement (interpretation #654). Bash-5.1 posix mode assignment statements preceding shell function calls do not persist after the function returns. 64. Bash-5.1 reverts to the bash-4.4 treatment of pathname expansion of words containing backslashes but no other special globbing characters. This comes after a protracted discussion and a POSIX interpretation (#1234). 65. In bash-5.1, disabling posix mode attempts to restore the state of several options that posix mode modifies to the state they had before enabling posix mode. Previous versions restored these options to default values. 66. Bash-5.2 attempts to prevent double-expansion of array subscripts under certain circumstances, especially arithmetic evaluation, by acting as if the `assoc_expand_once' shell option were set. 67. The `unset' builtin in bash-5.2 treats array subscripts `@' and `*' differently than previous versions, and differently depending on whether the array is indexed or associative. Shell Compatibility Level ========================= Bash-4.0 introduced the concept of a `shell compatibility level', specified as a set of options to the shopt builtin (compat31, compat32, compat40, compat41, and so on). There is only one current compatibility level -- each option is mutually exclusive. The compatibility level is intended to allow users to select behavior from previous versions that is incompatible with newer versions while they migrate scripts to use current features and behavior. It's intended to be a temporary solution. This section does not mention behavior that is standard for a particular version (e.g., setting compat32 means that quoting the rhs of the regexp matching operator quotes special regexp characters in the word, which is default behavior in bash-3.2 and above). If a user enables, say, compat32, it may affect the behavior of other compatibility levels up to and including the current compatibility level. The idea is that each compatibility level controls behavior that changed in that version of bash, but that behavior may have been present in earlier versions. For instance, the change to use locale-based comparisons with the `[[' command came in bash-4.1, and earlier versions used ASCII-based comparisons, so enabling compat32 will enable ASCII-based comparisons as well. That granularity may not be sufficient for all uses, and as a result users should employ compatibility levels carefully. Read the documentation for a particular feature to find out the current behavior. Bash-4.3 introduced a new shell variable: BASH_COMPAT. The value assigned to this variable (a decimal version number like 4.2, or an integer corresponding to the compatNN option, like 42) determines the compatibility level. Starting with bash-4.4, bash has begun deprecating older compatibility levels. Eventually, the options will be removed in favor of the BASH_COMPAT variable. Bash-5.0 is the final version for which there will be an individual shopt option for the previous version. Users should use the BASH_COMPAT variable on bash-5.0 and later versions. The following table describes the behavior changes controlled by each compatibility level setting. The `compatNN' tag is used as shorthand for setting the compatibility level to NN using one of the following mechanisms. For versions prior to bash-5.0, the compatibility level may be set using the corresponding compatNN shopt option. For bash-4.3 and later versions, the BASH_COMPAT variable is preferred, and it is required for bash-5.1 and later versions. compat31 - the < and > operators to the [[ command do not consider the current locale when comparing strings; they use ASCII ordering - quoting the rhs of the [[ command's regexp matching operator (=~) has no special effect compat32 - the < and > operators to the [[ command do not consider the current locale when comparing strings; they use ASCII ordering - interrupting a command list such as "a ; b ; c" causes the execution of the next command in the list (in bash-4.0 and later versions, the shell acts as if it received the interrupt, so interrupting one command in a list aborts the execution of the entire list) compat40 - the < and > operators to the [[ command do not consider the current locale when comparing strings; they use ASCII ordering. Bash versions prior to bash-4.1 use ASCII collation and strcmp(3); bash-4.1 and later use the current locale's collation sequence and strcoll(3). compat41 - in posix mode, `time' may be followed by options and still be recognized as a reserved word (this is POSIX interpretation 267) - in posix mode, the parser requires that an even number of single quotes occur in the `word' portion of a double-quoted ${...} parameter expansion and treats them specially, so that characters within the single quotes are considered quoted (this is POSIX interpretation 221) compat42 - the replacement string in double-quoted pattern substitution is not run through quote removal, as it is in versions after bash-4.2 - in posix mode, single quotes are considered special when expanding the `word' portion of a double-quoted ${...} parameter expansion and can be used to quote a closing brace or other special character (this is part of POSIX interpretation 221); in later versions, single quotes are not special within double-quoted word expansions compat43 - the shell does not print a warning message if an attempt is made to use a quoted compound assignment as an argument to declare (declare -a foo='(1 2)'). Later versions warn that this usage is deprecated. - word expansion errors are considered non-fatal errors that cause the current command to fail, even in posix mode (the default behavior is to make them fatal errors that cause the shell to exit) - when executing a shell function, the loop state (while/until/etc.) is not reset, so `break' or `continue' in that function will break or continue loops in the calling context. Bash-4.4 and later reset the loop state to prevent this compat44 - the shell sets up the values used by BASH_ARGV and BASH_ARGC so they can expand to the shell's positional parameters even if extended debug mode is not enabled - a subshell inherits loops from its parent context, so `break' or `continue' will cause the subshell to exit. Bash-5.0 and later reset the loop state to prevent the exit - variable assignments preceding builtins like export and readonly that set attributes continue to affect variables with the same name in the calling environment even if the shell is not in posix mode compat50 (set using BASH_COMPAT) - Bash-5.1 changed the way $RANDOM is generated to introduce slightly more randomness. If the shell compatibility level is set to 50 or lower, it reverts to the method from bash-5.0 and previous versions, so seeding the random number generator by assigning a value to RANDOM will produce the same sequence as in bash-5.0 - If the command hash table is empty, bash versions prior to bash-5.1 printed an informational message to that effect even when writing output in a format that can be reused as input (-l). Bash-5.1 suppresses that message if -l is supplied - Bash-5.1 and later use pipes for here-documents and here-strings if they are smaller than the pipe capacity. If the shell compatibility level is set to 50 or lower, it reverts to using temporary files. compat51 (set using BASH_COMPAT) - The `unset' builtin will unset the array a given an argument like `a[@]'. Bash-5.2 will unset an element with key `@' (associative arrays) or remove all the elements without unsetting the array (indexed arrays) - arithmetic commands ( ((...)) ) and the expressions in an arithmetic for statement can be expanded more than once - expressions used as arguments to arithmetic operators in the [[ conditional command can be expanded more than once - indexed and associative array subscripts used as arguments to the operators in the [[ conditional command (e.g., `[[ -v') can be expanded more than once. Bash-5.2 behaves as if the `assoc_expand_once' option were enabled. - the expressions in substring parameter brace expansion can be expanded more than once - the expressions in the $(( ... )) word expansion can be expanded more than once - arithmetic expressions used as indexed array subscripts can be expanded more than once; - `test -v', when given an argument of A[@], where A is an existing associative array, will return true if the array has any set elements. Bash-5.2 will look for a key named `@'; - the ${param[:]=value} word expansion will return VALUE, before any variable-specific transformations have been performed (e.g., converting to lowercase). Bash-5.2 will return the final value assigned to the variable, as POSIX specifies; - Parsing command substitutions will act as if extended glob is enabled, so that parsing a command substitution containing an extglob pattern (say, as part of a shell function) will not fail. This assumes the intent is to enable extglob before the command is executed and word expansions are performed. It will fail at word expansion time if extglob hasn't been enabled by the time the command is executed. ------------------------------------------------------------------------------- Copying and distribution of this file, with or without modification, are permitted in any medium without royalty provided the copyright notice and this notice are preserved. This file is offered as-is, without any warranty.