
特定のディレクトリに含まれるすべての Java クラスを、ディレクトリの先頭から逆コンパイルしようとしています。
ディレクトリには多くのサブディレクトリがあり、それぞれの深さは異なります。
私がやりたいのは、各ディレクトリに移動し、コンテンツがサフィックスを持つファイルである場合に.class
、逆コンパイラ コマンドを実行して、同じディレクトリに逆コンパイルされたファイルを作成することです。
以下のことを試しましたが、目的を達成できませんでした。
最初の方法は次のとおりです。
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
JADがどのように機能するかについては100%確信はありませんが、このREADMEファイルで見つけた情報、この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
答え2
jadはこの組み込み機能をサポートしています、文書によると再帰的な globも含めて glob を展開します**
。したがって、ドキュメントからコピーした次の例の cmd のように、引用符を使用して glob をシェルから保護します。
jad -o -r -sjava -dsrc 'tree/**/*.class'
このコマンドは、 のすべてのサブディレクトリにあるすべての .class ファイルを逆コンパイルし
tree
、 のクラスのパッケージ名に従って のサブディレクトリに出力ファイルを作成しますsrc
。たとえば、 ファイルに パッケージ のtree/a/b/c.class
クラスが含まれている場合、出力ファイルの名前は になります。c
a.b
src/a/b/c.java
ディレクトリ構造の選択肢が気に入ったら、これがほぼ間違いなく最良のオプションです。これがないと、パッケージ構造がディレクトリに変換されないようです。ディレクトリ構造を使用して、ファイルをファイルの隣に-r
配置できるかどうかはわかりません。.java
.class
find -execdir
正しいディレクトリでjadを実行するために使用する:
# untested
find [more find options] -name '*.class' -execdir jad {} +
これは、cd
少なくとも 1 つの を含むすべてのディレクトリに効果的に適用され.class
、そこで を実行するのと同等の処理が行われます。(複数の引数を 1 つのコマンドにグループ化するには、 ではなく を使用することjad *.class
に注意してください)。+
\;
GNUfind
は強力です。読んでくださいマニュアルページ。
またはbashの機能を使用する:
for dir in ./*
bash を使用しているので、 bash の globstar 機能を使用して再帰的に実行できます。これは、大きなディレクトリ ツリーの場合よりも大幅に遅くなります。これは、bash が、ディレクトリであるかどうかを確認するためにすべての dir エントリを調べる必要がないように、find
によって返されるファイル タイプのヒントを利用することを知らないためです。ただし、bash の再帰 glob は便利です。readdir
lstat
# 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 がディレクトリのみに一致することに注意してください。
答え3
私にとって効果的な解決策を思いつきました:
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
if
ファイルがクラス ファイルでない場合、jad は逆コンパイルを実行しないため、ファイルの正しいタイプを確認するためのステートメントは必要ありません。