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.
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.
$() Command Substitution According to the official GNU Bash Reference manual: “Command substitution allows the output of a command to replace the command itself.
$ 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
#!/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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With