निर्देशिकाओं के माध्यम से पुनरावर्ती लूप और निर्देशिका में एक फ़ाइल पर एक कमांड चलाएं


6

मैं एक निश्चित निर्देशिका में निहित सभी जावा कक्षाओं को डिकम्पाइल करने की कोशिश कर रहा हूं, जो निर्देशिका के शीर्ष पर शुरू होता है।

निर्देशिका में कई उपनिर्देशिकाएँ होती हैं और प्रत्येक की गहराई अलग-अलग होती है।

मैं जो करना चाहता हूं वह प्रत्येक डायरेक्टरी में जाता है और यदि कंटेंट प्रत्यय वाली फाइल है .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

क्या इनमें से एक को प्राप्त करने के लिए ट्विक किया जा सकता है जो मुझे चाहिए? पहले आदेश को पुनरावर्ती ऑपरेशन में कैसे बदला जा सकता है?

जवाबों:


3

मैं 100% ठोस नहीं हूं कि कैसे JAD ठीक काम करता है, लेकिन इसके आधार पर जानकारी मुझे इस 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। इस तरह की समस्याओं को हल करने की कुंजी यह समझना है कि आप पहले व्यक्ति नहीं हैं जो कमांड लाइन आउटपुट को किसी अन्य गंतव्य पर आउटपुट करना चाहते थे।


मुझे लगता है कि आपने मेरे प्रश्न का गलत अर्थ निकाला है। मैं एक निश्चित निर्देशिका के भीतर निहित सभी वर्गों को विघटित करना चाहता हूं।
Ares

@ जोकर मुझे यह भी पक्का नहीं है कि मैंने इसका गलत अर्थ कैसे निकाला होगा। यह कमांड शीर्ष से शुरू होने वाली सभी निर्देशिकाओं को खोजता है, पाता है .class फ़ाइलें और फिर एक कमांड चलाता है जो JAD के विघटित आउटपुट को उस की मूल निर्देशिका में आउटपुट करेगा .class फ़ाइल।
JakeGould

1
मेरी गलती, मैंने आपके उत्तर को अच्छी तरह से देखा नहीं था। यह इरादा के रूप में काम करता है, धन्यवाद।
Ares

1
आपको उपयोग करना चाहिए while IFS= read -r class या कुछ और। केवल पर्यावरण के संस्करणों के लिए ऊपरी-केस नामों का उपयोग करना अच्छा है, और IFS + का उपयोग कर सेटिंग -r कुछ समस्याओं से बचा जाता है । इस समस्या को हल करने के अन्य बेहतर तरीके हैं हालांकि, उदा। मेरा जो केवल एक बार प्रति फ़ाइल के बजाय निर्देशिका में एक बार जद के स्टार्टअप ओवरहेड का भुगतान करता है। (या एक बार पूरे पेड़ के लिए अगर जद का बिल्ट-इन है ** विस्तार करता है कि ओपी को क्या चाहिए)।
Peter Cordes

1

इस निर्मित के लिए jad का समर्थन है , प्रलेखन के अनुसार । यह आपके लिए ग्लब्स का विस्तार करेगा, जिसमें शामिल हैं ** पुनरावर्ती ग्लब्स। इसलिए उन्हें शेल से बचाने के लिए उद्धरणों का उपयोग करें, जैसे कि इस उदाहरण 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 यह निर्देशिकाओं में पैकेज संरचना को चालू नहीं करेगा। IDK अगर आप इसे डाल करने के लिए मिल सकता है .java के बगल में फ़ाइलें .class आपकी निर्देशिका संरचना के साथ फ़ाइलें।


का उपयोग करते हुए find -execdir सही निर्देशिका में जेड चलाने के लिए :

# untested
find [more find options]  -name '*.class' -execdir jad {} +

यह प्रभावी रूप से होगा cd हर निर्देशिका के लिए जिसमें कम से कम एक हो .class, और चलने के बराबर करते हैं jad *.class क्या आप वहां मौजूद हैं। (ध्यान दें + के बजाय \; एक कमान में कई आर्ग्स समूह के लिए)।

जीएनयू find शक्तिशाली है; पढ़ना मैन पेज


या बैश सुविधाओं का उपयोग करें :

चूंकि आप बैश का उपयोग कर रहे हैं, आप बना सकते हैं for dir in ./* बैश ग्लोबस्टार सुविधा के साथ पुनरावर्ती। की तुलना में यह काफी धीमी है find बड़ी निर्देशिका के पेड़ों के लिए, क्योंकि यह बैश फाइल-प्रकार संकेत का लाभ लेना नहीं जानता है 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

ग्लोब मैच केवल निर्देशिका बनाने के लिए एक अनुगामी स्लेश के उपयोग पर ध्यान दें।


0

मैं एक समाधान के साथ आया हूं जो मेरे लिए काम करता है:

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 आवश्यक विवरण, सही प्रकार की फ़ाइल की जांच करने के लिए क्योंकि जद डिकम्पाइल नहीं करेगा यदि फ़ाइल एक क्लास फ़ाइल नहीं है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.