31

Is there any sh code that is not syntactically valid bash code (won't barf on syntax)?

I am thinking of overwriting sh with bash for certain commands.

  • How do you define "valid" for your purposes? – Michael Homer May 11 '18 at 03:58
  • well I guess there is sourceable and runnable, maybe those are 2 different things – Alexander Mills May 11 '18 at 06:00
  • 1
    I guess by valid I meant syntactically valid, so it won't barf on syntax – Alexander Mills May 11 '18 at 06:01
  • meaning bash won't ever barf when it sees sh syntax – Alexander Mills May 11 '18 at 06:37
  • 2
    Different tokenizing? e.g. (( comes to mind. – ccorn May 11 '18 at 16:00
  • 1
    For some distros /usr/bin/sh is just a sym-link to /usr/bin/bash (I'm using CentOS 7.3 and it is). You should check to see if sh is really bash for your distro. – Centimane May 11 '18 at 16:41
  • @Centimane that is interesting maybe I can use /bin/bash instead of /bin/sh for some stuff – Alexander Mills May 11 '18 at 23:39
  • 1
    A few years ago, my whole project broke when something was "upgraded" in bash. I had to change all my shebang lines from #!/bin/sh to #!/bin/bash. Then everything worked again, so you do really have to be careful. It may have happened when they started using dash instead of bash for sh. – Joe May 11 '18 at 23:43
  • 2
    @Joe, that's the opposite of what the OP is asking for -- you had bash code that was mislabeled as being sh code but wasn't. The OP is asking if they can have (actual, not mislabeled) sh code that breaks when it runs with bash, not if they can have bash code that breaks when it runs with sh (which is obvious -- if bash extensions didn't have any effect on available language features, they wouldn't be extensions). – Charles Duffy May 12 '18 at 20:01
  • @charlesduffy Not exactly. My code was honestly intended to be sh code and had worked as such for years. There well may have been bashisms in it, but I was unawaware of any issues. My code certainly wasn't "mislabeled." – Joe May 13 '18 at 05:52
  • @Joe, ...if you still have that code, you might paste it into http://shellcheck.net/ with a #!/bin/sh shebang; it won't catch every bashism, but it at least finds a good number of them. And yes, I know you intended your code to be compatible with /bin/sh, but there's practical evidence that it wasn't :) – Charles Duffy May 13 '18 at 18:02
  • Funny that OP leads to a point where accepting only 1 answer would generally be wrong – Alexander Mills Dec 16 '22 at 04:52

2 Answers2

48

Here is some code that does something different in POSIX sh and Bash:

hello &> world

Whether that is "invalid" for you I don't know.

In Bash, it redirects both standard output and standard error from hello into the file world. In POSIX sh, it runs hello in the background and then makes an empty redirection into world, truncating it (i.e. it's treated as & >).

There are plenty of other cases where Bash extensions will do their thing when run under bash, and would have different effects in a pure POSIX sh. For example, brace expansion is another, and it too operates the same under Bash's POSIX mode and not.


As far as static syntax errors go, Bash has both reserved words (like [[ and time) not specified by POSIX, such that [[ x is valid POSIX shell code but a Bash syntax error, and a history of various POSIX incompatibility bugs that may result in syntax errors, such as the one from this question:

x=$(cat <<'EOF'
`
EOF
)
bash: line 2: unexpected EOF while looking for matching ``'
bash: line 5: syntax error: unexpected end of file

Syntax-errors-only is a pretty dangerous definition of "invalid" for any circumstance where it matters, but there it is.

Michael Homer
  • 76,565
  • 3
    Note that while brace expansion currently makes bash (and zsh, pdksh, ksh93) non-compliant, POSIX is working at adding provision in the specification to allow brace expansion (and {fd}>file a similar issue), so that bash can be conformant again (brace expansion would stay unspecified, but compliant scripts would need to do echo "{a,b}" is they want {a,b} to be output). See discussion that started it – Stéphane Chazelas May 11 '18 at 08:39
  • 2
    Also relevant to this Q&A: http://austingroupbugs.net/view.php?id=1191#c3983 – Stéphane Chazelas May 11 '18 at 08:40
  • 2
    Would someone writing a script in POSIX sh ever write a command like this? The OP is going from sh to bash, and from my understanding this seems like it would be more of a problem going in the other direction? – Rich May 11 '18 at 15:10
  • 1
    @Rich: Sure. I don't use any systems where /bin/sh is bash, so if I weren't actively aware of this bashism, writing a command line this could easily happen. The spacing in the answer makes it look unlikely, but hello&>world is less far-fetched. – R.. GitHub STOP HELPING ICE May 11 '18 at 15:21
  • I thought the OP was clear that the example is asking for a case where valid POSIX sh syntax is not also valid bash syntax. "Behaves differently" != "invalid syntax". – Charles Duffy May 11 '18 at 21:48
  • The OP was very much not clear on what "valid" meant, and I suspect still isn't really. – Michael Homer May 11 '18 at 23:19
  • 1
    @Rich Most of them are pretty unlikely, which is why Bash was able to repurpose the syntax like that. The question is whether there is any code that isn't "valid", though, and there is on all fronts (behaviourally by design, syntactically by design, and bugs). You could write something in the POSIX dialect and it wouldn't work in Bash. – Michael Homer May 11 '18 at 23:22
  • 1
    @CharlesDuffy, I think the clarification about "not barfing on syntax" was added after this answer was initially written. In any case, the non-syntactic differences can still cause problems regarding the actual job the script is doing, so it's not like they're completely ignorable. – ilkkachu May 12 '18 at 19:59
  • 2
    I actually saw a bug due to the &> difference just last month! – Gordon Davisson May 13 '18 at 08:12
16

A short example:

time()(:)

time in Bash is a reserved word, and behaves differently from the time program. It's quite likely you'll break some practical scripts trying to parse the result of time by using bash. But technically it is not a syntax error. Redefining time as a function would be rare but causes a syntax error as this question specifies.

A shorter example:

a():

Valid in dash, but not POSIX compliant.

user23013
  • 1,087
  • 1
  • 9
  • 18
  • 3
    More generally, any word that is a nonstandard keyword or a builtin command in Bash will cause the same effect. In addition to time, there's stuff like declare, function, select, and coproc. Though some of those are explicitly marked as unspecified in the standard (keywords and builtins/utilities), but I can't see e.g. time or coproc in the list. And using --posix doesn't seem to help. – ilkkachu May 11 '18 at 16:05