0

With the python --version as input in the terminal, I'd like to confirm (also in the shell in the form of shell programming) whether any python versions installed are 3 or higher. For example,

Python 3.2.1

Would yield True or some form of confirmation, where as python2.2p1 or Python 2.1.4 would yield False.

I've tried using regex through sed or grep, but can't get it.

Note, this is a different matter from what some think to be a duplicate of, as I'm asking the shell programming code that can automate confirmation of python3 or higher being installed, not a way to manually check it (just entering python --version).

Shrike
  • 9,218
  • 7
  • 68
  • 105
Jin Chun
  • 21
  • 1
  • 3
  • 1
    See https://stackoverflow.com/questions/8917885/which-version-of-python-do-i-have-installed – Wiktor Stribiżew May 24 '19 at 13:57
  • 3
    Isn't that the output when Python is *not* installed? – Benjamin W. May 24 '19 at 13:58
  • In your case it seems like python is not installed at all. To capture this case you should ask your package manager instead of using `python -V`. Which package manager do you use? is it `apt`? Also, if you want to use version 3 then call `python3` instead of just `python`. – Socowi May 24 '19 at 13:58
  • This output is from the [Ubuntu `command-not-found`](https://launchpad.net/ubuntu/+source/command-not-found) hook for Bash. It should not even run from within a script, to my understanding. – tripleee May 24 '19 at 14:24
  • Oops. You're right. Edited. – Jin Chun May 24 '19 at 15:25
  • 2
    This is not a dupe, at least not of the chosen dupe target. The question here is not how to get Python to report its version (the subject of the dupe target and all its answers), but rather *how to write a shell script* that interprets that (and perhaps other) output. – John Bollinger May 24 '19 at 16:24
  • This sounds like an extremely trivial task - [edit] your question to show what you have tried and state what part do you need help with. – Ed Morton May 25 '19 at 12:18

3 Answers3

2

With the python --version as input in the terminal, I'd like to confirm (also in the shell in the form of shell programming) whether any python versions installed are 3 or higher.

If the python command launches any version of cpython, then the output of python --version (to its stderr, not stdout) will have the form:

Python X.Y.Z

You can test that in a shell script like so:

if python --version 2>&1 | grep -q '^Python 3\.'; then
  # It's python 3 ...
else
  # It's not python 3; maybe not installed
fi

Note that the output you originally presented in the question indicated that Python was not installed at all. The above approach will execute the else branch in that event. Note also that it is possible for Python to be installed with a different name -- for example, on the system where I am typing this, python is Python 2.7.5, but Python 3.4.8 is available via the command python3. You could extend the above to test some possible alternative names for Python 3, but you cannot safely, reliably, or efficiently perform an exhaustive test for whether Python 3 is installed at all, under any name or path.

John Bollinger
  • 160,171
  • 8
  • 81
  • 157
  • On reconsidering, I think this should be the made the accepted answer, and my solution is over engineered considering the requirement. – Alex Harvey May 26 '19 at 10:07
1

The easiest way to do this in Bash is using sort -V.

To solve the problem of comparing version strings in general in bash, here is an simple compare() function that accepts two arguments a and b and returns true if a <= b. And then some unit tests showing its validity for various Python version inputs:

# test.sh

compare() {
  local a=$1 ; local b=$2
  [ "$( (echo "$a" ; echo "$b") | sort -V | head -1)" == "$a" ]
}

test22p1() {
  compare "2.2p1" "3.0.0"
  assertTrue "$?"
}

test214() {
  compare "2.1.4" "3.0.0"
  assertTrue "$?"
}

test300() {
  compare "3.0.0" "3.0.0"
  assertTrue "$?"
}

test372() {
  compare "3.7.2" "3.0.0"
  assertFalse "$?"
}

. shunit2

Output:

▶ bash test.sh
test22p1
test214
test300
test372

Ran 4 tests.

OK

(Those unit tests assume that shunit2 is installed of course.)

About the function:

It just echoes $a then $b on two separate lines, pipes into sort -V, and takes the head. If the head is equal to the left-hand side, true is returned ; otherwise if it is equal to the right-hand side, false is returned.

In your question you mentioned you really want to know if Python 3 or greater is installed, so you could modify it and have something like this instead:

python3_installed() {
  local a b
  a=$(python --version 2>&1 | perl -pe 's/python *//i') ; b=3
  [ "$( (echo "$a" ; echo "$b") | sort -V | head -1)" == "$b" ]
}

This function will compute the actual version of Python installed, and compare it to "3" using sort -V and return false unless 3 or greater is installed.

Note use of Perl there to do a case-insensitive regex search and replace. (Not all sed's have the case-insensitive ability.)

The great thing about doing it this way is you can then have readable code when you call it, like:

if python3_installed ; then
  # yes it is!
else
  # ...
fi

Finally, according to the docs for sort -V (from the BSD manual; POSIX doesn't specify a -V option, but most sorts seem to have it):

`-V, --version-sort`

Sort version numbers. The input lines are treated as file names in form PREFIX VERSION SUFFIX, where SUFFIX matches the regular expression (.([A-Za-z~][A-Za-z0-9~]*)?)*. The files are compared by their prefixes and versions (leading zeros are ignored in version numbers, see example below). If an input string does not match the pattern, then it is compared using the byte compare function. All string comparisons are performed in C locale, the locale environment setting is ignored.

Alex Harvey
  • 14,494
  • 5
  • 61
  • 97
-2

Here is sample awk script to do the job:

echo $(python --version) | awk 'BEGIN{found="false"}/python-3/{found="true"}END{print found}'
Dudi Boy
  • 4,551
  • 1
  • 15
  • 30
  • 2
    That's a [useless use of `echo`](https://stackoverflow.com/questions/11710552/useless-use-of-cat#echo). And it does nothing to reveal which version you have. – tripleee May 24 '19 at 14:25
  • echo is used to provide standard-out to awk. Without the echo command, awk requires input file. – Dudi Boy May 24 '19 at 14:27
  • 2
    No, you are completely mistaken. If Python prints the version information to standard output, the pipe feeds that to Awk's standard input just as well as from `echo`; and if it doesn't, your `echo` doesn't help at all. – tripleee May 24 '19 at 14:30
  • ... and it doesn't. `python --version` directs its output to stderr, not stdout. Moreover, its error output when `python` is a version-3 cpython does not match `/python3/`. – John Bollinger May 24 '19 at 14:38