A shell script to search multiple jar files for a Java class or pattern

I’ve found that there are times when I need to be able to find a Java class inside of a jar file. Usually this happens when something isn’t working, and I get something like a Java ClassNotFoundException. In the process of debugging this problem — especially if I’m using a jar library that I haven’t used before — I list the contents of one or more jar files to debug the problem.

This isn’t a problem if I only have to search in one jar file for the missing class, but when I have to search several jar files, doing this manually is a real pain, and it gets even worse if your jar files are organized in a directory hierarchy. So I created the following shell script that lets me search all my jar files at one time for the class at hand.

In the example shown below, I had just started working with XFire, and I’m searching all my jar files (including sun-directories that contain jar files) for the pattern codehaus/xfire/spring:

#!/bin/sh

LOOK_FOR="codehaus/xfire/spring"

for i in `find . -name "*jar"`
do
  echo "Looking in $i ..."
  jar tvf $i | grep $LOOK_FOR > /dev/null
  if [ $? == 0 ]
  then
    echo "==> Found \"$LOOK_FOR\" in $i"
  fi
done

That’s the pattern the script looks like, and if you’ve seen any shell scripts I’ve written before you can see that the pattern is very familiar. First, I execute the command `find . -name "*jar"`, then feed that output into a standard Bourne shell for loop. Then, for each file found, I run the jar tvf command, then grep for patterns that match my LOOK_FOR pattern. If the pattern is found (which I can tell because the exit code of the grep command will be 0) I then use the echo command to show that the pattern has been matched.

That describes how the shell script works, and the output below shows what you can expect to see when you run this command:

$ ./searchjars.sh

Looking in ./activation-1.1.jar ...
Looking in ./commons-beanutils-1.7.0.jar ...
Looking in ./commons-codec-1.3.jar ...
Looking in ./commons-collections-3.2.jar ...
Looking in ./commons-dbcp.jar ...
Looking in ./commons-httpclient-3.0.jar ...
Looking in ./commons-pool.jar ...
Looking in ./jaxen-1.1-beta-9.jar ...
Looking in ./jaxws-api-2.0.jar ...
Looking in ./jdom-1.0.jar ...
Looking in ./jsr173_api-1.0.jar ...
Looking in ./mail-1.4.jar ...
Looking in ./saaj-api-1.3.jar ...
Looking in ./saaj-impl-1.3.jar ...
Looking in ./spring.jar ...
Looking in ./stax-api-1.0.1.jar ...
Looking in ./wsdl4j-1.6.1.jar ...
Looking in ./wstx-asl-3.2.0.jar ...
Looking in ./xbean-2.2.0.jar ...
Looking in ./xbean-spring-2.8.jar ...
Looking in ./xfire-aegis-1.2.6.jar ...
Looking in ./xfire-annotations-1.2.6.jar ...
Looking in ./xfire-core-1.2.6.jar ...
Looking in ./xfire-java5-1.2.6.jar ...
Looking in ./xfire-jaxws-1.2.6.jar ...
Looking in ./xfire-jsr181-api-1.0-M1.jar ...
Looking in ./xfire-spring-1.2.6.jar ...
==> Found "codehaus/xfire/spring" in ./xfire-spring-1.2.6.jar
Looking in ./XmlSchema-1.1.jar ...

As you can see from this output, this script searches a fairly large number of jar files for you, then shows which jar (or jars) has a file in it that matches your desired pattern.