Now, Which Jar Did I Put That In?
Imagine this scenario: you've got a directory full of jar files, and your build is failing because it's missing some classes that are in one of them. You're not sure which; only that the missing classes are in here somewhere.
I've been running into this problem a lot lately, as I try to convert a series of old Ant builds over to Maven. At times, I've found that the jar name doesn't even come close to indicating whether it contains the key classes I need to make my build start working. To address this problem, I've started a short Ruby script that I'm tentatively calling jargrep.rb.
Before I show you this, please remember that I'm a little green when it comes to Ruby, so there may be some elegant one-liner that I'm missing here or there...and it may look decidedly Java-ish to the "native" Ruby programmer. Oh, and I'm not looking to win any architectural or OO-design awards here; I only needed a script to scratch a very persistent itch. Finally, this script is lacking a lot of polish when it comes to options I might want to include, etc. For this, I'd use OptionParser, but I couldn't be bothered to lookup the syntax, etc. today when I needed this script...
jargrep.rb
#!/usr/bin/ruby if ( ARGV.length < 2 ) STDOUT.puts "Searches jar archives for files within that match a particular pattern.\n" STDOUT.puts "Usage: #{$0} <pattern> -" STDOUT.puts "\tRead jar list from standard in, searching them for the specified pattern." STDOUT.puts "\t\t-OR-" STDOUT.puts "Usage: #{$0} <pattern> <file> [<file>]*" STDOUT.puts "\tSearch the jars in the file list for the specified pattern." STDOUT.puts "\n\nNOTES:" STDOUT.puts "\n\t1. Does NOT use egrep (yet)." STDOUT.puts "\n\t2. Currently, lists matches in the following format:" STDOUT.puts "\n\t\t<jar-file-name[0]>:\n" STDOUT.puts "\n\t\t<matching-path-within-jar[0]>" STDOUT.puts "\n\t\t<matching-path-within-jar[1]>" STDOUT.puts "\n\t\t<matching-path-within-jar[2]>" STDOUT.puts "\n\n\t\t<jar-file-name[1]>:\n" STDOUT.puts "\n\t\t<matching-path-within-jar[0]>" STDOUT.puts "\n\t\t..." exit 1 end pattern = ARGV[0] if ( ARGV[1] == '-' ) files = STDIN.read files.each_line do |file| file.chomp! matches = `jar tvf #{file} | grep #{pattern}`.chomp # status = $?.exitstatus # STDOUT.puts "jar returned with status: #{status} for file: #{file}" if matches.index( 'java.util.zip.ZipException' ) == 0 STDOUT.puts "\n\n!!!\nFailed to search jar: #{file}\nError:\n\n#{match}!!!\n\n" elsif ( !matches.empty? ) STDOUT.puts "\n#{file}:\n\n#{matches}" end end else ARGV.shift ARGV.each do |file| file.chomp! matches = `jar tvf #{file} | grep #{pattern}`.chomp if ( !matches.empty? ) STDOUT.puts "\n#{file}:\n\n#{matches}" end end end
Have you ever run into a situation like this? How did you solve it? Remember, each time I run across a problem like this, I fully expect to see it come up again, so I'm not looking for the ideal linux command line to execute one time then lose once it rolls out of my .bash_history file... Anyway, for what it's worth, enjoy.
Re: Now, Which Jar Did I Put That In?
I've done something similar with Java/Groovy: it is _very_ useful and I'm a kindred spirit in terms of solving a problem with a tool that can be used over and over again.
The grep-ish name is fine. I call mine "which" in homage to the Unix command of the same name.
ps. I haven't looked at the Ruby code closely but it can be useful to have the program recursively descend subdirectories.
Re: Now, Which Jar Did I Put That In?
Re: Now, Which Jar Did I Put That In?
linux: grep MyClass *.jar */*.jar */*/*.jar
linux: grep MyClass `find . -name '*.jar'`
There are more (more accurate) commands, but these are simple and do the trick most of the time.
Re: Now, Which Jar Did I Put That In?
It ain't exactly pretty since we keep adding features ad hoc, but it works.
