5

I wrote a shell script that uses a few BASH specific commands, such as [[ ... ]]. I know that some BASH features are only available in BASH 4 or newer. How can I find out what version of BASH I need for this script without trying numerous different versions?

Is there some kind of tool that can check the needed minimum version?

The source code is available on GitHub at https://github.com/JEFF-Media-GbR/RandomRound/blob/master/randomround

Benjamin W.
  • 46,058
  • 19
  • 106
  • 116
mfnalex
  • 833
  • 5
  • 16
  • 1
    Don't bother. Use the script. If/when one of your users reports an issue with an older version, then start to worry about it, and at that point you know at least one lower bound on the required version. – William Pursell Aug 15 '17 at 12:38
  • 2
    @WilliamPursell: I actually wanted to avoid exactly that. – mfnalex Aug 15 '17 at 12:47
  • 1
    Then write a portable shell script and avoid bashisms completely. Don't go half way. If you're going to write non-portable code, then expect it to break for some group of users. Attempting to version match is a pointless exercise. – William Pursell Aug 15 '17 at 13:03
  • @WilliamPursell Thanks, but this does not answer my question how to find out what version I need for a script I already have – mfnalex Aug 15 '17 at 13:07
  • Yes, it does. You wait until someone hits a bug with an older version. Barring that, you run your script through all possible versions of bash. Or you comb through the changelogs finding exactly when every single feature you use was added and then you confirm that it doesn't work by running your script on the older version in question. Either way, its much less work to just rewrite the script to be portable. – William Pursell Aug 15 '17 at 13:10
  • This debate is similar to feature testing vs browser sniffing in web dev. Even if you detect the right version, there are global bash settings that can turn features on or off breaking your script on the right version. – yxre Aug 15 '17 at 14:01
  • Thanks to everyone, I think I am just going to declare the required bash version for my script as the one I am using, which is 4.3. – mfnalex Aug 15 '17 at 14:50
  • @LelandBarton, ...those global settings are for the greatmost part at known values when a noninteractive script is started. This is a serious problem for content that's meant to be sourced into an interactive shell, to be sure, but a noninteractive one... not as much. Yes, we could possibly be compiled with `xpg_echo` on-by-default, but anyone who depends on `echo -e` is living in sin (and it's only particularly prone to causing breakage when scripts are executed with bash in POSIX mode after being written with a dependency on said compliance-breaking bashism). – Charles Duffy Aug 15 '17 at 14:58
  • @mfnalex, ...I've been known to put in a header that checks `$BASH_VERSION` and aborts with an explicit error when a known-incompatible one is in use. Better than a hard-to-understand error message later. – Charles Duffy Aug 15 '17 at 14:59
  • If you're trying to write a bash script that's compatible with most bashes in the wild, the thing you have to worry about is bash 3.2 on OS X. That script doesn't use associative arrays so you should be okay ... but I'd just test it with bash 3.2 and the latest 4.x release ... If you want an external tool that doesn't actually run the script, then use shellcheck https://www.shellcheck.net/ ... I don't think it can check for compatibility with old bashes, but it can check for POSIX sh compatibility (a stronger requirement). – Greg Nisbet Aug 15 '17 at 15:10
  • @GregoryNisbet Thanks, I tried my new version with Bash 3.2 on macOS and after installing coreutils and creating a symlink from /usr/local/bin/shuf to /usr/local/bin/gshuf, everything worked. So I should be safe by stating it is compatible at least with Bash 3.2+ – mfnalex Aug 15 '17 at 15:34
  • 1
    @mfnalex I see. There's a difference between bash itself and the external commands that bash invokes. The only bash-specific feature you are using in that script as far as I can tell is the array syntax. You're better off sticking to bash ... converting it to POSIX sh requires using `$@` inside a function, dynamically generating variable names, or using a temporary file. As for the external commands, you have to be careful about what commands you use and how if you want the script as a whole to be portable. Here's a possible `shuf` replacement https://stackoverflow.com/a/6511327/931154 – Greg Nisbet Aug 15 '17 at 15:53

2 Answers2

3

There are a bunch of resources to check for a) introduction of a specific Bash feature and b) Bashisms in general:

These can all be used to figure out when a feature was introduced.

For a list of Bashisms, the Bash manual describes differences to the Bourne Shell in Appendix B ("Major differences from the Bourne Shell"), and there is the article How to make bash scripts work in dash on the Wooledge wiki.

I don't know what the distribution of versions "in the wild" is, but if your user base includes macOS users, be aware that they use Bash 3.2 unless they have upgraded using Homebrew or similar.

As for programmatically determining what version of Bash is required to run a specific script, I'm not aware of any tool that does that. Shellcheck comes somewhat close in that it can warn about Bashisms when your script starts with #!/bin/sh.

Benjamin W.
  • 46,058
  • 19
  • 106
  • 116
  • 1
    Thanks, I tried my new version with Bash 3.2 on macOS and after installing coreutils and creating a symlink from /usr/local/bin/shuf to /usr/local/bin/gshuf, everything worked. So I should be safe by stating it is compatible at least with Bash 3.2+. I will see through the changelist prior to 3.2 and try if I can find anything related to the expressions/functions I have used. – mfnalex Aug 15 '17 at 15:36
0

What you are asking can not be done. This is one of the programming problems which are principally impossible to solve. One (but not the only) reason is that a script may at run time construct a string and evaluate it, and there is no way that you can by automatic means analyze for an arbitrary program, what data it will produce.

user1934428
  • 19,864
  • 7
  • 42
  • 87