Skip to content
Advertisement

Bash script to create symbolic links to shared libraries

I think this question is rather easy for you shell scripting monsters.

I am looking for the most elegant and shortest way to create symbolic links to shared libraries for Unix by means of a bash shell script.

What I need is starting out with a list of shared library files such as “libmythings.so.1.1, libotherthings.so.5.11”, get the symbolic links created such as:

libmythings.so -> libmythings.so.1 -> libmythings.so.1.1
libotherthings.so -> libotherthings.so.5 -> libotherthings.so.5.11

The library files are inside a directory which contains other files such as other shell scripts.

EDIT: Well, “ldconfig -nN .” could work OK, but I also need the link without the major number of the library appended after “.so”, at least one of the libraries, since one or more libraries are the entry points of JNI calls from Java, so when a library is instanced by means of System.loadlibrary(“libraryname”) it expects a library called “libraryname.so”, not “libraryname.so.X”.

The solution with just ldconfig -nN could work if there were a workaround for the Java part.

Advertisement

Answer

for baselib in "$@"
do
     shortlib=$baselib
     while extn=$(echo $shortlib | sed 's/.[0-9][0-9]*$//')
           [ -n "$extn" ]
     do
         shortlib=$(basename $shortlib $extn)
         ln -s $baselib $shortlib
     done
done

I’ve cheated – all the links go to the base library (libmythings.so.1.1); if you really want to chain, then you need:

for baselib in "$@"
do
     shortlib=$baselib
     while extn=$(echo $shortlib | sed 's/.[0-9][0-9]*$//')
           [ -n "$extn" ]
     do
         shorterlib=$(basename $shortlib $extn)
         ln -s $shortlib $shorterlib
         shortlib=$shorterlib
     done
done           

Beware – untested code.


Hubris precedes nemesis.

Comment arrived that the code above doesn’t work – and the comment is correct. A fixed version with test in situ is:

set -- libname.so.5.1.1

for baselib in "$@"
do
    shortlib=$baselib
    while extn=$(echo $shortlib | sed -n '/.[0-9][0-9]*$/s/.*(.[0-9][0-9]*)$/1/p')
          [ -n "$extn" ]
    do
        shortlib=$(basename $shortlib $extn)
        echo ln -s $baselib $shortlib
    done
done

The change is in the sed command. This version doesn’t print anything by default (-n), matches only lines ending with a dot followed by digits, and then deletes everything except that suffix, and prints what remains for assignment to extn. As amended, the script generates the output below. Remove the echo to get it to execute the link commands.

ln -s libname.so.5.1.1 libname.so.5.1
ln -s libname.so.5.1.1 libname.so.5
ln -s libname.so.5.1.1 libname.so

The script illustrates an interesting and often overlooked point about shell scripts: the sequence of operations in the condition block of a while need not be a single command. The status of the line with the edit operation doesn’t affect whether the test as a whole succeeds; the exit status of the last command, the ‘[ -n "$extn" ]‘, controls whether the loop continues.

Advertisement