How to compare versions in a Bash script? (Solved)

For discussions about programming, programming questions/advice, and projects that don't really have anything to do with Puppy.
Post Reply
Message
Author
linus.cl
Posts: 126
Joined: Wed 02 Apr 2014, 14:09
Location: Germany
Contact:

How to compare versions in a Bash script? (Solved)

#1 Post by linus.cl »

Hello!

How can I compare two versions in my Bash script?

I have two versions:

Code: Select all

2.7.1-i486s 2.3-2-spup 
^new          ^old
They are saved in two variables: $newversion and $oldversion
I try to compare them.

I hope, you can help me... :D
Last edited by linus.cl on Sat 30 Aug 2014, 20:00, edited 1 time in total.

User avatar
6502coder
Posts: 677
Joined: Mon 23 Mar 2009, 18:07
Location: Western United States

#2 Post by 6502coder »

You mean that you just want to test two shell variables to see if they are the same string? That's easy:

Code: Select all

if [ $newversion  =  $oldversion ]
then
	echo same
else
	echo different
fi

linus.cl
Posts: 126
Joined: Wed 02 Apr 2014, 14:09
Location: Germany
Contact:

#3 Post by linus.cl »

No, i'd like to check if $newversion is newer.

I found an application: vercmp.
https://www.archlinux.org/pacman/vercmp.8.html

But I can't use it. (I don't understand it)

User avatar
RSH
Posts: 2397
Joined: Mon 05 Sep 2011, 14:21
Location: Germany

#4 Post by RSH »

Code: Select all

if vercmp ${NEWVERSION} gt ${OLDVERSION} ; then 
	echo $NEWVERSION
fi
[b][url=http://lazy-puppy.weebly.com]LazY Puppy[/url][/b]
[b][url=http://rshs-dna.weebly.com]RSH's DNA[/url][/b]
[url=http://murga-linux.com/puppy/viewtopic.php?t=91422][b]SARA B.[/b][/url]

User avatar
MochiMoppel
Posts: 2084
Joined: Wed 26 Jan 2011, 09:06
Location: Japan

#5 Post by MochiMoppel »

linus.cl wrote:I found an application: vercmp.
No need for an application. Try this:

Code: Select all

newversion="2.7.1-i486s"
oldversion="2.3-2-spup"
[[ "$newversion" > "$oldversion" ]] && echo "newversion is newer" || echo "oldversion is newer"
The > operator compares 2 strings by their alphabetic ASCII order. Requires a double bracket test construct to work.

gcmartin

#6 Post by gcmartin »

Hello @Linus.cl

Noticing some of the very good things you are aiming into the community, you may find this tool to have "tremendous " advantage to your use and development efforts. Install and observe. It will meet much much more than you ask while accelerating your work efforts. And, there is no system penalty in its presence as a tool.

Here to help

jamesbond
Posts: 3433
Joined: Mon 26 Feb 2007, 05:02
Location: The Blue Marble

#7 Post by jamesbond »

There are a few versions of "vercmp" floating around. Since you're building for Puppy, might as well use Puppy's own vercmp. It's here: https://github.com/puppylinux-woof-CE/w ... t/vercmp.c. If you google "barry kauler vercmp" you will find a few links.
Fatdog64 forum links: [url=http://murga-linux.com/puppy/viewtopic.php?t=117546]Latest version[/url] | [url=https://cutt.ly/ke8sn5H]Contributed packages[/url] | [url=https://cutt.ly/se8scrb]ISO builder[/url]

User avatar
technosaurus
Posts: 4853
Joined: Mon 19 May 2008, 01:24
Location: Blue Springs, MO
Contact:

#8 Post by technosaurus »

sort -V or sort --version-sort works too
use head -n1 or tail -n1 for the oldest/newest (works for comparing 2 or more)
Check out my [url=https://github.com/technosaurus]github repositories[/url]. I may eventually get around to updating my [url=http://bashismal.blogspot.com]blogspot[/url].

User avatar
Karl Godt
Posts: 4199
Joined: Sun 20 Jun 2010, 13:52
Location: Kiel,Germany

#9 Post by Karl Godt »

I would use case for that

Code: Select all

case $BASH_VERSION in
1.*) : do_something;;
2.[0-2].*) : do_something_else;;
2.3.*) echo OLD VERSION;;
2.[4-6].*) : do_something_else_more;;
2.7.*) echo NEW VERSION;;
*) echo UNHANDLED bash version $BASH_VERSION;;
esac
5.2 Bash Variables

These variables are set or used by Bash, but other shells do not normally treat them specially.

BASH_VERSINFO

A readonly array variable (see Arrays) whose members hold version information for this instance of Bash. The values assigned to the array members are as follows:

BASH_VERSINFO[0]

The major version number (the release).
BASH_VERSINFO[1]

The minor version number (the version).
BASH_VERSINFO[2]

The patch level.
BASH_VERSINFO[3]

The build version.
BASH_VERSINFO[4]

The release status (e.g., beta1).
BASH_VERSINFO[5]

The value of MACHTYPE.

BASH_VERSION

The version number of the current instance of Bash.

http://www.gnu.org/software/bash/manual ... oking-Bash


Bash version 2.Y may not know some of these variables .
«Give me GUI or Death» -- I give you [[Xx]term[inal]] [[Cc]on[s][ole]] .
Macpup user since 2010 on full installations.
People who want problems with Puppy boot frugal :P

goingnuts
Posts: 932
Joined: Sun 07 Dec 2008, 13:33
Contact:

#10 Post by goingnuts »

From above inputs I put together below shell-version of vercmp which also works with ash/busybox only systems:

Code: Select all

#!/bin/sh
help () {
	echo "usage: vercmp-shell version1 lt|gt|le|ge|eq version2
       return value 0 if true, else 1"
}

[ $# -ne 3 ] && help && exit 2


case "$2" in
	lt)		[ "$1" != "$3" ] && [ "$(echo $1,$3 | tr ',' '\n' | sort -k1,1n | head -n1)" = "$1" ] && exit 0 || exit 1;;
	gt)	[ "$1" != "$3" ] && [ "$(echo $1,$3 | tr ',' '\n' | sort -k1,1n | tail -n1)" = "$1" ] && exit 0 || exit 1;;
	le)	[ "$1" = "$3" ] || [ "$(echo $1,$3 | tr ',' '\n' | sort -k1,1n | head -n1)" = "$1" ] && exit 0 || exit 1;;
	ge)	[ "$1" = "$3" ] || [ "$(echo $1,$3 | tr ',' '\n' | sort -k1,1n | tail -n1)" = "$1" ] && exit 0 || exit 1;;
	eq)	[ "$1" = "$3" ] && exit 0 || exit 1;;
	*) 	help && exit 1;;
esac

exit

User avatar
MochiMoppel
Posts: 2084
Joined: Wed 26 Jan 2011, 09:06
Location: Japan

#11 Post by MochiMoppel »

Nice. However unlike the binary vercmp it might give false results when the version string contains commas, e.g. "GNU bash, version 4.4.12(1)-release (i686-pc-linux-gnu)"

I think it would be better to change

Code: Select all

echo $1,$3 | tr ',' '\n' | sort -k1,1n
to something more robust like

Code: Select all

printf '%s\n%s' "$1" "$3" | sort -k1,1n
Would still work with ash

goingnuts
Posts: 932
Joined: Sun 07 Dec 2008, 13:33
Contact:

#12 Post by goingnuts »

Agree - thanks for improvement input! :D
Follow up 20200503: For robustness one could also change from:

Code: Select all

echo $1,$3 | tr ',' '\n' | sort -k1,1n
to:

Code: Select all

echo $1/$3 | tr '/' '\n' | sort -k1,1n
or to eliminate the use of tr one could change to:

Code: Select all

echo -e "$1\n$3" | sort -k1,1n
The printf is sure best way but not all systems has it - echo seems more likely to be everywhere...but might not always support -e though.

Post Reply