Using Terminal to open a file within a jar file?

Solution 1:

Personally I use jar because it feels more natural, and allows for other operations such as updating contents too. Here are the read commands:

List contents

jar tf myjar.jar

Extract contents to pwd

jar xf myjar.jar

Extract specific file, creating dirs as required

jar xf myjar.jar /foo/bar.class

Extracting the bytecode itself isn't usually terribly useful though. To make sense of it, you need to decompile it into something readable.

There aren't many good java decompilers to choose from. I tend to use JD-GUI, because it's quick and does what I need it to. Frustratingly, its multi-file search functionality never works for me (note that Ctrl+F search-on-the-page is fine). This is no great loss though; you can get it to dump all the sources to disk with Ctrl+Alt+S for perusal with grep/vim/Eclipse etc.

I install it like this:

wget http://jd.benow.ca/jd-gui/downloads/jd-gui-0.3.5.linux.i686.tar.gz
tar xzf jd-gui-0.3.5.linux.i686.tar.gz
sudo mv jd-gui /usr/local/bin/
sudo chown root:root /usr/local/bin/jd-gui
sudo chmod 755 /usr/local/bin/jd-gui

Using it goes something like this:

jd-gui myjar.jar
Ctrl+Alt+S; pick your path & save
Alt+F4
jar xf <path>/myjar.src.zip 

Note however that JD-GUI has no CLI interface. If you know of a good CLI decompiler, I'd be very interested to hear of it (there is JAD, but AFAIK that only supports Java < 1.5).

Solution 2:

Using unzip you can pipe a file from the archive to stdout and then into something else to read it, like:

unzip -p /path/to/some.jar path/to/file/inside/jar | less

From memory unzip is not installed by default so you might need to:

sudo apt-get install unzip

Jeff

Solution 3:

jar files are really only zip files you can test this by doing.

file foo.jar

so to list the files you can simple do.

unzip -l foo.jar

To access the files just unzip the file with

unzip foo.jar

If you want to extract only one file then append the files after

unzip foo.jar some/path/in/jar/bar.class

Make sure to use the full path from -l. And keep in mind it will create the same path locally.

Solution 4:

(No rep points, so have to answer to respond to comments by @Kurro)

unzip (-p | -c) <jar-file> <file-in-jar>

The -p and -c options extract the file to standard output; -c gives an extra 2 lines of data at the beginning (which JAR file and which file within the archive).

I found this extremely convenient for reading the Manifest file or the .xml files. For the compiled .class files, this is useless, but your friend here is javap:

javap -classpath <jar-file> <fully.qualified.class.name>    # without the .class suffix

Some useful options are: -c (decompile to Java Assembly), -private to also show private fields, and -verbose for lots of extra information. If it's a big file, you may want to pipe the output through less.