Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to increment version number in a shell script?

Tags:

bash

wine

The following simple version control script is meant to find the last version number of a given file, increment it, run a given command with the newly created file (e.g., editor), and after that save it to stable. Since it's simple, it doesn't check anything since the script would be modified as needed. For instance, if the result won't be stable, the user can omit the last argument.

However, one major concern of the current functionality is how to implement the following: if the last section after dot has two digits, inc untill 99; if only 1, then inc until 9, then move to the previous section. The versions may have any positive integer number of sections.

1.2.3.44 -> 1.2.3.45 1.2.3.9 -> 1.2.4.0 1.2.3 -> 1.2.4 9 -> 10 

The remaining issue is that it doesn't wait for a tabbed wine editor to close the file; the goal is to detect when the tab is closed. Also, could you explain how best to make sure that my variable names don't overwrite existing ones?

You can also offer other improvements.

#!/bin/bash #Tested on bash 4.1.5 #All arguments in order: "folder with file" "file pattern" cmd [stable name] folder="$1" file_pattern="$2" cmd="$3" stable="$4"  cd "$folder" last_version=$(ls --format=single-column --almost-all | \     grep "$file_pattern" | \     sed -nr 's/^[^0-9]*(([0-9]+\.)*[0-9]+).*/\1/p' | \     sort -Vu | \     tail -n 1) last_version_file=$(ls --format=single-column --almost-all | \     grep "$file_pattern" | \     grep $last_version | \     tail -n 1) #tail -n 1 is only needed to get 1 line if there are backup files with the same version number new_version=$(echo $last_version | \     gawk -F"." '{$NF+=1}{print $0RT}' OFS="." ORS="") #increments last section indefinitely new_version_file=$(echo "$last_version_file" | \     sed -r "s/$last_version/$new_version/") cp "$last_version_file" "$new_version_file" "$cmd" "$new_version_file" & \     wait #works with gedit but not with wine tabbed editor [[ "$stable" ]] && \     cp "$new_version_file" "$stable" #True if the length of string is non-zero. 

Update: The following works on my pc, I will update it if improvements or solutions to unsolved problems are found:

#!/bin/bash inc() { shopt -s extglob     num=${last_version//./}     let num++      re=${last_version//./)(}     re=${re//[0-9]/.}')'     re=${re#*)}      count=${last_version//[0-9]/}     count=$(wc -c<<<$count)     out=''     for ((i=count-1;i>0;i--)) ; do         out='.\\'$i$out     done      sed -r s/$re$/$out/ <<<$num }  folder="$1" file_pattern="$2" cmd="$3" stable="$4"  cd "$folder" last_version=$(ls --format=single-column --almost-all | \     grep "$file_pattern" | \     sed -nr 's/^[^0-9]*(([0-9]+\.)*[0-9]+).*/\1/p' | \     sort -Vu | \     tail -n 1) #--almost-all do not list implied . and .. last_version_file=$(ls --format=single-column --almost-all | \     grep "$file_pattern" | \     grep $last_version | \     tail -n 1) #tail -n 1 is only needed to get 1 line if there are backup files with the same version number new_version=$(inc) new_version_file=$(echo "$last_version_file" | \     sed -r "s/$last_version/$new_version/") cp "$last_version_file" "$new_version_file" "$cmd" "$new_version_file" && \     wait #works with gedit but not tabbed wine editor [[ "$stable" ]] && \     cp "$new_version_file" "$stable" #True if the length of string is non-zero. 

I appreciate the variety of solutions that have been offered, for they help with gaining a perspective and drawing a comparison.

like image 887
nnn Avatar asked Dec 28 '11 04:12

nnn


People also ask

How do you increment version numbers?

There are simple rules that indicate when you must increment each of these versions: MAJOR is incremented when you make breaking API changes. MINOR is incremented when you add new functionality without breaking the existing API or functionality. PATCH is incremented when you make backwards-compatible bug fixes.

What is $() in bash script?

$() Command Substitution According to the official GNU Bash Reference manual: “Command substitution allows the output of a command to replace the command itself.


Video Answer


1 Answers

$ echo 1.2.3.4 | awk -F. -v OFS=. 'NF==1{print ++$NF}; NF>1{if(length($NF+1)>length($NF))$(NF-1)++; $NF=sprintf("%0*d", length($NF), ($NF+1)%(10^length($NF))); print}' 1.2.3.5 

1.2.3.9  => 1.2.4.0 1.2.3.44 => 1.2.3.45 1.2.3.99 => 1.2.4.00 1.2.3.999=> 1.2.4.000 1.2.9    => 1.3.0 999      => 1000 

UPDATE:

#!/usr/bin/gawk -f  BEGIN{     v[1] = "1.2.3.4"     v[2] = "1.2.3.44"     v[3] = "1.2.3.99"     v[4] = "1.2.3"     v[5] = "9"     v[6] = "9.9.9.9"     v[7] = "99.99.99.99"     v[8] = "99.0.99.99"     v[9] = ""      for(i in v)         printf("#%d: %s => %s\n", i, v[i], inc(v[i])) | "sort | column -t" }  function inc(s,    a, len1, len2, len3, head, tail) {     split(s, a, ".")      len1 = length(a)     if(len1==0)         return -1     else if(len1==1)         return s+1      len2 = length(a[len1])     len3 = length(a[len1]+1)      head = join(a, 1, len1-1)     tail = sprintf("%0*d", len2, (a[len1]+1)%(10^len2))      if(len2==len3)         return head "." tail     else         return inc(head) "." tail }  function join(a, x, y,    s) {     for(i=x; i<y; i++)         s = s a[i] "."     return s a[y] } 

$ chmod +x inc.awk $ ./inc.awk #1:  1.2.3.4      =>  1.2.3.5 #2:  1.2.3.44     =>  1.2.3.45 #3:  1.2.3.99     =>  1.2.4.00 #4:  1.2.3        =>  1.2.4 #5:  9            =>  10 #6:  9.9.9.9      =>  10.0.0.0 #7:  99.99.99.99  =>  100.00.00.00 #8:  99.0.99.99   =>  99.1.00.00 #9:  =>           -1 
like image 177
kev Avatar answered Sep 28 '22 21:09

kev