Atom Feed SITE FEED   ADD TO GOOGLE READER

Stupid Bash Tricks: Find a file in a pile of jars

My latest code depends on ServiceMBeanSupport.class from JBoss. The problem is that JBoss is composed of dozens of .jar files and I'm not sure which one contains the file I'm interested in.

Tools
  • find this command will list all the files that meet the specified metadata. It can also execute a command for each file found, using that filename as a parameter. For example, to remove all the CVS folders in a directory tree, type find . -name CVS -exec rm -rf {} \; . Find will substitute {} for the file that's found and it needs \; to designate the end of the command.
  • grep give input text, grep prints only the lines that match my regular expression.
  • bash -c executes the bash shell. This can be used with find -exec to run multiple commands in sequence
  • jar tvf print all the files in a .jar file

    Find my file in a jar
    jar tvf jarfile | grep ServiceMBeanSupport.class

    This will tell me if the file is in the jar file or not. Its a start.

    Find my file in all the .jar files in the current directory or deeper
    find . -name *.jar -exec jar tvf {} | grep ServiceMBeanSupport.class \;

    This will tell me if the file is in any of the jarfiles. Unfortunately it doesn't tell me which jarfile it is in, since it just prints the contents of the jarfiles and not their names.

    The Command
    find . -name *.jar -exec bash -c "echo {} && jar tvf {} | grep ServiceMBean " \;

    This writes the name of the jar file, followed by any matching file's that are in it. So if I search for ServiceMBean, I get a list like this:

    ./client/jboss-iiop-client.jar
    
    ...
    ./client/jboss-net-client.jar
    ./client/jboss-system-client.jar
    ./client/jboss-transaction-client.jar
    ./client/jbossall-client.jar
    795 Fri Jun 25 19:55:16 EDT 2004 org/jboss/jmx/adaptor/rmi/RMIAdaptorServiceMBean.class
    1331 Fri Jun 25 19:55:16 EDT 2004 org/jboss/jmx/connector/ConnectorFactoryServiceMBean.class
    ./lib/jboss-system.jar
    603 Fri Jun 25 19:54:38 EDT 2004 org/jboss/system/ListenerServiceMBean.class
    1745 Fri Jun 25 19:54:38 EDT 2004 org/jboss/system/ListenerServiceMBeanSupport$MBeanInfo.class
    10950 Fri Jun 25 19:54:38 EDT 2004 org/jboss/system/ListenerServiceMBeanSupport.class
    1309 Fri Jun 25 19:54:38 EDT 2004 org/jboss/system/ServiceMBean.class
    9523 Fri Jun 25 19:54:38 EDT 2004 org/jboss/system/ServiceMBeanSupport.class
    ...


    And my work is done for the day. Cool, eh?
  • Put this script on your path in a file called 'findinjar' and chmod u+x the file:

    #!/bin/bash
    find . -name *.jar -exec bash -c "echo {} && jar tvf {} | grep $1" \;
    Try this:

    #!/bin/bash
    find "$1" -name "*.jar" -a -exec bash -c "jar tvf {} | grep $2" \; -print

    This takes a dir and a match string and _only_ outputs lines and files that match

    or change the "grep $2" to:
    grep -m 1 $2 > /dev/null

    and it will only output matching file names

    gcowsar
    This was just what I looked for...

    Here is a small improvement to show only the jars that do contain the file (helps if you search through a lot of jars)

    find . -name *.jar -exec bash -c "echo {}: && jar tvf {} | grep $1 ; echo __DELIMITER__ " \; | awk 'BEGIN { FS="\n"; RS="\n__DELIMITER__" }; NF > 2 '