find -exec cmd {} + vs | xargs


115

फ़ाइलों के एक बहुत बड़े सेट पर कौन सा अधिक कुशल है और इसका उपयोग किया जाना चाहिए?

find . -exec cmd {} +

या

find . | xargs cmd

(मान लें कि फ़ाइल नाम में कोई मज़ेदार पात्र नहीं हैं)


जवाबों:


107

गति का अंतर महत्वहीन होगा।

लेकिन आपको यह सुनिश्चित करना होगा कि:

  1. आपकी स्क्रिप्ट यह नहीं मानेगी कि किसी फ़ाइल में फ़ाइल नाम में स्थान, टैब आदि नहीं होगा; पहला संस्करण सुरक्षित है, दूसरा नहीं है।

  2. आपकी स्क्रिप्ट -एक विकल्प के रूप में " " से शुरू होने वाली फ़ाइल का इलाज नहीं करेगी ।

तो आपका कोड इस तरह दिखना चाहिए:

find . -exec cmd -option1 -option2 -- {} +

या

find . -print0 | xargs -0 cmd -option1 -option2 --

पहला संस्करण छोटा और लिखने में आसान है क्योंकि आप 1 को नजरअंदाज कर सकते हैं, लेकिन दूसरा संस्करण अधिक पोर्टेबल और सुरक्षित है, क्योंकि " -exec cmd {} +" GNU खोज में एक अपेक्षाकृत नया विकल्प है (2005 से, बहुत सारे रनिंग सिस्टम अभी तक नहीं होंगे) और यह हाल ही में छोटी गाड़ी थी । बहुत सारे लोग इस " -exec cmd {} +" को नहीं जानते हैं , जैसा कि आप अन्य उत्तरों से देख सकते हैं।


4
-print0 एक GNU फ़ंड (और GNU xargs) विकल्प भी है जो बहुत सारे गैर-लिनक्स सिस्टम से गायब है, इसलिए पोर्टेबिलिटी का तर्क उतना मान्य नहीं है। सिर्फ प्रिंट का उपयोग करना और xargs की -0 है छोड़ना है, तथापि, है बहुत पोर्टेबल।
dannysauer

7
मुद्दा यह है कि -print0 के बिना यह काम नहीं करता है यदि किसी स्थान या टैब आदि के साथ कोई फ़ाइल है तो यह सुरक्षा भेद्यता हो सकती है जैसे कि "foo -o index.html" जैसा कोई फ़ाइल नाम है तो -o का इलाज किया जाएगा एक विकल्प के रूप में। खाली निर्देशिका में प्रयास करें: "स्पर्श - foo \ -o \ index.html; खोज। | xargs cat"। आपको मिलेगा: "बिल्ली: अमान्य विकल्प - 'ओ'"
Tometzky

2
उनका उदाहरण एक फ़ाइल नाम है जिसमें a - है। -Print0 के बिना, पता चलेगा ।/foo -o index.html। तो शायद - एक के साथ शुरू करना कोई बड़ी बात नहीं है, लेकिन इसका परिणाम थोड़ा बदला हुआ है, और एक बहुउद्देश्यीय प्रणाली पर, यदि आपकी स्क्रिप्ट दुनिया में पढ़ने योग्य है, तो एक हमला वेक्टर प्रदान कर सकता है।
बोबापुल

2
कुछ पर एक नोट जो मुझे यहाँ फँसाया है - execआउटपुट परिणाम का उपयोग कर के रूप में वे पाए जाते हैं, जो xargsहोगा, ऐसा लगता है, जब तक पूरी निर्देशिका को लिखने से पहले खोज नहीं की जाती है तब तक प्रतीक्षा करें। यदि आप एक बड़ी निर्देशिका पर यह कोशिश कर रहे हैं, और ऐसा लगता है कि xargsकाम नहीं कर रहा है, तो धैर्य उचित है।
FarmerGedden

1
@ बिना नए -print0रिटर्न के साथ अलग किए गए रिटर्न फाइलनाम को खोजा जाता है , लेकिन न्यूलाइन एक फ़ाइल नाम का भी हिस्सा हो सकता है, जो इसे अस्पष्ट बनाता है। बाइट 0 नहीं कर सकते, इसलिए यह एक सुरक्षित विभाजक है। हां - --एक कमांड को जोड़ना जो इसका समर्थन करता है एक अच्छा अभ्यास है जब आप इसके तर्कों को नियंत्रित नहीं कर सकते हैं, भले ही हमेशा सख्त या असुरक्षित न हो।
Tometzky

7
find . | xargs cmd

अधिक कुशल है (यह प्रत्येक मैच के लिए एक बार चलने के cmdविपरीत exec, जितना संभव हो उतना कम cmdबार चलता है )। हालाँकि, यदि आप फ़ाइल नाम रिक्त स्थान या कायरता वर्ण रखते हैं तो आप परेशानी में पड़ जाएंगे।

निम्नलिखित का उपयोग करने का सुझाव दिया गया है:

find . -print0 | xargs -0 cmd

इस भले ही फ़ाइल नाम फंकी वर्ण हो काम करेंगे ( -print0बनाता findNUL-समाप्त मैचों प्रिंट, -0बनाता है xargsइस प्रारूप की उम्मीद है।)


28
यह "नहीं मिल रहा है, -exec cmd {} \;" लेकिन "खोजें। -exec cmd {} +"। बाद वाला एक बार में एक फ़ाइल नहीं चलाएगा।
Tometzky

2
ध्यान दें कि xargsयदि फ़ाइल (या केवल कुछ) मिलान वाली फ़ाइलों के लिए दृष्टिकोण बहुत धीमा है, और cmdप्रत्येक फ़ाइल के लिए बहुत कुछ नहीं करना है। उदाहरण के लिए, जब एक खाली निर्देशिका में चलाया जाता है, तो xargsसंस्करण को कम से कम दो बार समय लगेगा, क्योंकि दो प्रक्रियाओं को केवल एक के बजाय शुरू किया जाना चाहिए। (हां, अंतर आमतौर पर * निक्स पर अगोचर है, लेकिन एक लूप में यह महत्वपूर्ण हो सकता है; या, इसे कुछ समय विंडोज पर आज़माएं ...)
सैमबी

2

आधुनिक xargs संस्करण अक्सर समानांतर पाइपलाइन निष्पादन का समर्थन करते हैं।

जाहिर है कि यह एक धुरी बिंदु हो सकता है जब यह पसंद के बीच आता है find … -exec और … | xargs

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