特定のディレクトリに含まれるすべてのJavaクラスを、ディレクトリの先頭から逆コンパイルしようとしています。
ディレクトリには多くのサブディレクトリがあり、それぞれの深さが異なります。
私がやりたいのは、各ディレクトリに移動し、コンテンツがサフィックス.class
のファイルである場合、decompilerコマンドを実行すると、同じディレクトリに逆コンパイルされたファイルが作成されます。
私は次のことを試しましたが、彼らは私が求めているものを達成していません。
最初の方法は次のとおりです。
for dir in ./*; do ( ( if [[ -d $dir ]]; then cd "$dir"; fi ) && ( for f in "$dir"; do ( if [[ -f $f && $f == *".class"* ]]; then jad "$f"; fi ); done ) ); done
ここでの問題は、再帰的ではないということです。たぶん、これは再帰的になるように微調整することができますか?
2番目の方法ははるかに単純でしたが、最上位ディレクトリにファイルを出力します。これは問題ないかもしれませんが、残念ながら、同じ名前のクラスがありますが、パッケージが異なるため、このソリューションも機能しません。
find . -type f -name "*.class" | while read filename; do echo $filename; done
これらの1つを微調整して、私が望むものを実現できますか?最初のコマンドを再帰操作に変換するにはどうすればよいですか?
私は自分に合った解決策を考え出しました。
find . -type d | while read dir; do ( if [[ -d $dir ]]; then cd $dir && find . -maxdepth 1 -type f | while read f; do ( jad $f ); done fi ); done
ファイルがクラスファイルでない場合、jadは逆コンパイルを実行しないため、正しいタイプのファイルをチェックするためにif
ステートメントは必要ありません。
私はJADが正確にどのように機能するかについて100%しっかりしているわけではありませんが、 このREADME file で見つけた情報に基づいて、このfind
コマンドはあなたにスタートを与える:
find . -type f -name '*.class' |\
while IFS= read -r Java_class_path
do
Java_dirname=$(dirname "${Java_class_path}")
jad -sjava -d"${Java_dirname}" "${Java_class_path}"
done
-s
オプションは出力拡張子を.Java
に設定し、-d
は元の.class
ファイルがfind
。このような問題を解決するための鍵は、コマンドライン出力を別の宛先に出力したいと思ったのはあなたが最初ではないことを理解することです。
jadはこの組み込み、 ドキュメントによる をサポートしています。 **
再帰グロブを含むグロブを拡張します。したがって、ドキュメントからコピーされた次の例のcmdのように、引用符を使用してシェルから保護します。
jad -o -r -sjava -dsrc 'tree/**/*.class'
このコマンドは、
tree
のすべてのサブディレクトリにあるすべての.classファイルを逆コンパイルし、クラスのパッケージ名に従ってsrc
のサブディレクトリに出力ファイルを作成します。たとえば、ファイルtree/a/b/c.class
にパッケージa.b
のクラスc
が含まれている場合、出力ファイルの名前はsrc/a/b/c.Java
になります。
ディレクトリ構造の選択が好きな場合、これはほぼ間違いなく最良のオプションです。 -r
がないと、パッケージ構造がディレクトリに変換されないようです。 IDKは、ディレクトリ構造を使用して.Java
ファイルの隣に.class
ファイルを配置できるかどうかを確認します。
find -execdir
を使用して正しいディレクトリでjadを実行する:
# untested
find [more find options] -name '*.class' -execdir jad {} +
これにより、少なくとも1つの.class
を含むすべてのディレクトリに効果的にcd
が実行され、そこでjad *.class
を実行するのと同じことが行われます。 (複数の引数を1つのコマンドにグループ化するには、+
ではなく\;
に注意してください)。
GNU find
は強力です。 manページ を読んでください。
またはbash機能を使用する:
Bashを使用しているので、bashのglobstar機能を使用してfor dir in ./*
を再帰的にすることができます。大きなディレクトリツリーの場合はfind
よりも大幅に遅くなります。これは、bashがreaddir
によって返されるファイルタイプのヒントを利用して、毎回lstat
する必要がないためです。それがディレクトリであるかどうかを確認するためのdirエントリ。しかし、bashの再帰的なグロブは便利です。
# untested
shopt -s globstar # put this in your .bashrc if you want it enabled all the time
for dir in ./**/; do
pushd "$dir"
classfiles=( *.class ) # expand the glob into an array
[[ -e $classfiles ]] && # test the first element of the array. Will fail if *.class didn't match anything.
jad *.class
popd "$dir"
done
末尾のスラッシュを使用して、globをディレクトリのみに一致させることに注意してください。