views:

272

answers:

6

I want to use a file to store the current version number for a piece of customer software which can be used by a start-up script to run the binary in the correct directory.

For Example, if the run directory looks like this:

.
..
1.2.1
1.2.2
1.3.0
run.sh
current_version

And current_version contains:

1.2.2

I want run.sh to descend into 1.2.2 and run the program foo.

The current solution is this:

!#/bin/sh
version = `cat current_version`
cd $version
./foo

It works but is not very robust. It does not check for file existence, cannot cope with multiple lines, leading spaces, commented lines, blank files, etc.

What is the most survivable way to do this with either a shell or perl script?

+5  A: 

That's a common approach. You can check for dir/file existence using test operators such as "if [ -d "somedirectory" ]; then" or [ -t "somefile" ]

I use symbolic links more often, though. Then, you can just change your symbolic link to use the version you want.

For example,

$ ln -s 1.2.2 current_version
$ ls -al
total 20
drwxr-xr-x 5 dbreese dbreese 4096 2008-09-15 13:34 .
drwxr-xr-x 3 dbreese dbreese 4096 2008-09-15 13:34 ..
drwxr-xr-x 2 dbreese dbreese 4096 2008-09-15 13:34 1.2.1
drwxr-xr-x 2 dbreese dbreese 4096 2008-09-15 13:34 1.2.2
drwxr-xr-x 2 dbreese dbreese 4096 2008-09-15 13:34 1.3.0
lrwxrwxrwx 1 dbreese dbreese    6 2008-09-15 13:34 current_version -> 1.2.2/

Then your script can just use "cd current_version".

Dustin
I want to avoid links because I don't want to disrupt existing instances of the program which might object to having their working directory changed.
Frosty
A: 

I would change the script to accept an argument. The argument should be a filename. Open the file using whatever scripting language you prefer [perl, python] and traverse the file until you find a match for your version.

I would use a regex... something along the lines of /\d\.\d\.\d/ . then have it execute the application through your script.

Nicholas Mancuso
A good solution but there is no guarantee that the version will remain x.x.x. The minor numbers might increase past 9 yielding something like 1.2.12 which would fail.
Frosty
@FrostyPerhaps /\d+\.\d+\.\d+/ would serve in that case?
Jon Ericson
A: 
Adam Rosenfield
I would like to gracefully handle slightly 'incorrect' version files. if the file had two lines, a leading space, a trailing space or something like that the original solution would fail.
Frosty
A: 
!#/bin/sh

if [ -e 'current_version' ]; then
    version=`cat current_version`;
    version=`echo $version | tr -ds [[:blank:]]`
    if [ -n "$version" ]; then
      if [ -d "$version" ]; then
         cd "$version"
      else
         echo $version is not a directory
      fi
    else
      echo version_file contained only blanks
    fi
else 
   No file named current_version exists
fi
slipset
This will fail unless there is a directory named $version. '$version' will always return the string $version and never expand the variable. Use double quotes instead: "$version".
Jon Ericson
A: 

If the versioning will always be in #.#.# format, you could do this:

ls | grep ^[0-9]\.[0-9]\.[0-9]$ | sort -nr | head -n 1

That will list the versions in descending numerical order, then selects the first of those

Peter Boughton
No guarantees on the version number. Also, I would like to be able to roll current_version back in the case where the latest version turns out to be unstable. Perhaps combining some sort of grep with the solution slipset gave would be best.
Frosty
A: 

What about:

#!/usr/bin/perl -w
use strict;
use warnings;

my $version_file = 'current_version';
open my $fh, '<', $version_file or die "Can't open $version_file: $!";

# Read version from file
my $version = <$fh>;
chomp $version;

# Remove whitespace (and match version)
die "Version format not recognized" if $version !~ m/(\d+\.\d+\.\d+)/;

my $dir = $1;
die "Directory not found: $dir" unless -d $dir;

# Execute program in versioned directory.
chdir $dir;
system("./foo");
Peter Stuifzand