web-dev-qa-db-ja.com

find = unzip、grepを使用して、JARのセットでJavaクラスを探す

Javaクラスを含むJARを見つけようとしました。JARはZip形式です。

私の最初の試みは:

$ find -name "*3.0.6.RELEASE.jar" | xargs -l1 unzip -l \
    | grep stereotype.Controller
      554  2011-08-18 16:49   org/springframework/stereotype/Controller.class
      554  2011-08-18 16:49   org/springframework/stereotype/Controller.class

クラスを見つけましたが、25の一致するファイルのどれに含まれているのかまだわかりません(2つのJARが含まれています)。そのため、途中でteeを使用してファイル名を出力することを考えました。

$ find -name "*3.0.6.RELEASE.jar" | tee - | xargs -l1 unzip -l \
    | grep stereotype.Controller
  554  2011-08-18 16:49   org/springframework/stereotype/Controller.class
  554  2011-08-18 16:49   org/springframework/stereotype/Controller.class
  554  2011-08-18 16:49   org/springframework/stereotype/Controller.class
  554  2011-08-18 16:49   org/springframework/stereotype/Controller.class

一致するファイルの場合は、ファイル名の後にController.classが続き、非処理の場合は次のファイル名が続くことを期待していました。しかし、今考えてみると、標準出力はパイプ内を流れ、xargsによって処理されるだけなので、理にかなっています。

標準エラーを使用することもできますが、プロセスが同時に実行されているため、タイミングの問題が発生し、出力が期待どおりの順序にならない可能性があります。

それで、この問題に取り組むより良い方法があるに違いありません、誰かがアイデアを持っていますか?

[〜#〜] update [〜#〜]:答えを待っている間、私はそのトリックを実行する恐ろしいPerlワンライナーを書きましたが、よりエレガントな解決策を見るのを楽しみにしています。

$ find -name "*3.0.6.RELEASE.jar" | Perl -e 'while (<>) { \
    $file=$_; @class=`unzip -l $_`; foreach (@class) { \
    if (/stereotype.Controller/) {print "$file $_";} } }'

出力:

./spring-context/3.0.6.RELEASE/spring-context-3.0.6.RELEASE.jar
   554  2011-08-18 16:49   org/springframework/stereotype/Controller.class
./org.springframework.context/3.0.6.RELEASE/org.springframework.context-3.0.6.RELEASE.jar
   554  2011-08-18 16:49   org/springframework/stereotype/Controller.class
6
stivlo

これを試して:

find -name "*3.0.6.RELEASE.jar" -exec sh -c 'unzip -l "{}" | grep -q stereotype.Controller' \; -print

ここでは、xargsforループは必要ありません。すべてを1つのfindで実行できます。 greppedされたコンテンツも出力する場合は、grep-qオプションを削除するだけですが、grepの一致が表示されることに注意してくださいbefore各ファイル名。より明確な出力を得るには、最後に-exec echo \;を追加できます。

8
rozcietrzewiacz

最初のワンライナーで、grepコマンドに-Hオプションを追加します。それは結果にファイル名を含めることです。

これはマンページからです-

-H, --with-filename
              Print the filename for each match.</strike>

[〜#〜]更新[〜#〜]

このスクリプトが役立つかもしれません-

#!/bin/bash

searchSTR="YOUR SEARCH"

for i in `find . -name "*jar"`
do
  echo "Scanning $i ..."
  jar tvf $i | grep $searchSTR > /dev/null
  if [ $? == 0 ]
  then
    echo "==> Found \"$searchSTR\" in $i"
  fi
done

ワンライナー:

for i in `find . -name "*.jar"`; do jar tvf $i | grep "search pattern" && echo $i ; done

唯一の悲しい部分は、grepコンテンツの後に表示されるjarファイルの名前です

2
jaypal singh

古いスレッドですが、これはこれを行うためのよりクリーンな方法のように見えます: http://alumnus.caltech.edu/~leif/opensource/cpcheck/CpCheckApp.html

Windows:
    cpcheck [flags] classpath [classpath]*
Unix:
    ./cpcheck.sh [flags] classpath [classpath]*
Java:
    Java -jar cpcheck.jar [flags] classpath [classpath]*
1
kisna