ディレクトリを再帰的にループし、ディレクトリ内のファイルに対してコマンドを実行します。

ディレクトリを再帰的にループし、ディレクトリ内のファイルに対してコマンドを実行します。

特定のディレクトリに含まれるすべての 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場所に基づいてファイル出力の宛先ディレクトリを設定します。このような問題を解決する鍵は、コマンド ライン出力を別の宛先に出力したいと思ったのは自分だけではないということを理解することです。.classfind

答え2

jadはこの組み込み機能をサポートしています文書によると再帰的な globも含めて glob を展開します**。したがって、ドキュメントからコピーした次の例の cmd のように、引用符を使用して glob をシェルから保護します。

jad -o -r -sjava -dsrc 'tree/**/*.class'

このコマンドは、 のすべてのサブディレクトリにあるすべての .class ファイルを逆コンパイルしtree、 のクラスのパッケージ名に従って のサブディレクトリに出力ファイルを作成します src。たとえば、 ファイルに パッケージ のtree/a/b/c.classクラスが含まれている場合、出力ファイルの名前は になります。ca.bsrc/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 は便利です。readdirlstat

# 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 は逆コンパイルを実行しないため、ファイルの正しいタイプを確認するためのステートメントは必要ありません。

関連情報