Extracting the classpath entries from a jar file's manifest Sometimes I need to search for dependencies in the classpath entries in the manifest of jar files. A jar manifest with classpaths looks like this:




Manifest-Version: 1.0
Created-By: 1.6.0_29 (Sun Microsystems Inc.)
Class-Path: spring-aop-3.2.0.jar spring-aspects-3.2.0.jar spring-beans
 -3.2.0.jar spring-context-3.2.0.jar spring-context-support-3.2.0.jar
 spring-core-3.2.0.jar spring-expression-3.2.0.jar spring-instrument-3
 .2.0.jar spring-instrument-tomcat-3.2.0.jar spring-jdbc-3.2.0.jar spr
 ing-jms-3.2.0.jar spring-orm-3.2.0.jar spring-oxm-3.2.0.jar spring-st
 ruts-3.2.0.jar spring-test-3.2.0.jar spring-tx-3.2.0.jar spring-web-3
 .2.0.jar spring-webmvc-3.2.0.jar spring-webmvc-portlet-3.2.0.jar



Searching for jars in a manifest is troublesome:


Extract the META-INF/MANIFEST.MF file from the jar
Re-join the split lines to make searching humanely possible


Step 2 is necessary, because of the line breaks. For example, I won't find "struts" in the above, because the word is broken in the middle.

I use this shell script to make this process easier, I call it jar-manifest-classpath.sh:



#!/bin/bash

if test -d "$TMPDIR"; then
    :
elif test -d "$TMP"; then
    TMPDIR=$TMP
elif test -d /var/tmp; then
    TMPDIR=/var/tmp
else
    TMPDIR=/tmp
fi
workdir=$TMPDIR/$(basename "$0")-work-$$

cleanup() {
    rm -fr "$workdir"
}

mkdir -p "$workdir"
trap 'cleanup' 1 2 3 15

for jar; do
    if ! test -f $jar; then
        echo warning: not a file: $jar
        continue
    fi
    [[ $jar = /* ]] || jar=$PWD/$jar
    (
        cd "$workdir" || exit 1
        jar xf "$jar"
        sed -ne '/^Class-Path:/,$p' META-INF/MANIFEST.MF | sed -e 's/^Class-Path: //' -e 's/^ //' | tr -d '\n' | tr ' ' '\n'
    )
done

cleanup


For a jar file with the manifest as above, this will output:




spring-aop-3.2.0.jar
spring-aspects-3.2.0.jar
spring-beans-3.2.0.jar
spring-context-3.2.0.jar
spring-context-support-3.2.0.jar
spring-core-3.2.0.jar
spring-expression-3.2.0.jar
spring-instrument-3.2.0.jar
spring-instrument-tomcat-3.2.0.jar
spring-jdbc-3.2.0.jar
spring-jms-3.2.0.jar
spring-orm-3.2.0.jar
spring-oxm-3.2.0.jar
spring-struts-3.2.0.jar
spring-test-3.2.0.jar
spring-tx-3.2.0.jar
spring-web-3.2.0.jar
spring-webmvc-3.2.0.jar
spring-webmvc-portlet-3.2.0.jar



This is much more pleasent, and perfectly grep-able.

Let me know if you have any ideas to improve or simplify!
(The script is part of my collection on GitHub)
I would create the trap for cleanup before an action is done that needs cleanup, so change the sequence of commands. Also I would prefer signal names instead of numbers. If you add EXIT to the signal list then cleanup is called when the shell is exited, so you can remove the last line of your script (cleanup)

trap 'cleanup' EXIT SIGHUP SIGINT SIGQUIT SIGTERM
mkdir -p "$workdir"


If the script is called without argument or with-? a usage message should be displayed.

Warnings and error messages should be written to stderr(2) and not to stdout(1). This is Unix standard behaviour for a program. Otherwise you will not see the error message if you pipe the output through a grep command.