Search code examples
linuxbashgreppiping

Searching jar or tar from bash


This seems like a simple bash task, but I cannot figure out how to do it. In this particular instance it is in regards to the jar command, but is equally applicable to the tar command.

Enough set up, here's the question:

I use the following bash command to search for a file within a jar:

jar -tf com.my.jarfile.jar | grep some_search_text

Simple enough. Now, I have a directory of jar files, and what I would really like is a command which can tell me which jars contain a file whose name contains a given string. Is this possible?

Background Problem: I have a file which has accidentally proliferated through a few jar files in my project. I would like to determine which jar files contain this file. The command above is a little different in that it will output files from the jar that match the pattern. I am less interested in knowing the names of the matching files within the jar as I am just which jars contain matches.


Solution

  • Assuming you're interested in the jar files which contain files where the file name matches your target string, you can write a simple loop:

    search="some_search_text"
    for file in *.jar
    do
        echo "$file"
        jar -tf "$file" | grep -e "$search"
    done
    

    This will echo each jar file's name, and then if the jar file contains a file whose name matches the search string, that will be shown. The -e ensures that there's no confusion even if your search string starts with a dash.

    If you don't want the non-matching names to appear, then:

    search="some_search_text"
    for file in *.jar
    do
        match=$(jar -tf "$file" | grep -e "$search")
        if [ -n "$match" ]
        then
            echo "$file"
            echo "$match"
        fi
    done
    

    And if you simply want the jar file name to appear if it contains a file whose name matches, then (obviously):

    search="some_search_text"
    for file in *.jar
    do
        match=$(jar -tf "$file" | grep -e "$search")
        if [ -n "$match" ]
        then
            echo "$file"
        fi
    done
    

    Though that can be shrunk to:

    search="some_search_text"
    for file in *.jar
    do
        [ -n "$(jar -tf "$file" | grep -e "$search")" ] && echo "$file"
    done
    

    Both the jar and tar commands process one of their files per invocation; there isn't a way to have a single invocation process multiple files.

    If you're really interested in jar files where the jar file contains anything that matches your search text, then you can use:

    search="some_search_text"
    
    grep -e "$search" -l *.jar
    

    The -l lists the jar files by name. This works sanely even though the typical jar file contains binary data.