遞歸循環遍歷目錄並對目錄中的檔案運行命令

遞歸循環遍歷目錄並對目錄中的檔案運行命令

我試著從目錄頂部開始反編譯某個目錄中包含的所有 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

這裡的問題是它不是遞歸的。也許這可以以遞歸的方式進行調整?

第二種方法較簡單,但它輸出頂層目錄中的檔案。雖然這可能沒問題,但不幸的是,我有具有相同名稱但位於不同包中的類,因此該解決方案也不起作用:

find . -type f -name "*.class" | while read filename; do echo $filename; done

可以調整其中一個來實現我想要的嗎?如何將第一個命令轉換為遞歸操作?

答案1

我並不是 100% 確信 JAD 的工作原理,但基於我在此自述文件中找到的訊息,這個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。因此,請使用引號來保護它們免受 shell 的影響,例如從文件複製的 cmd 範例:

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於至少包含一個 的每個目錄.class,並執行與在那裡運行相同的操作jad *.class。 (請注意,+而不是\;將多個參數分組到一個命令中)。

GNUfind很強大;讀手冊頁


或使用 bash 功能:

由於您使用的是 bash,因此可以for dir in ./*使用 bash 的 globstar 功能進行遞迴。它find比大目錄樹慢得多,因為 bash 不知道利用返回的檔案類型提示來readdir避免lstat每個目錄條目都查看它是否是目錄。但 bash 遞歸 glob 可能很有用。

# 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 將不會執行反編譯。

相關內容