खोजें: -exec बनाम xargs (उर्फ "xargs basename" क्यों तोड़ता है?)


10

मैं उपनिर्देशिकाओं में फैले एक निश्चित प्रकार की सभी फाइलों को खोजने की कोशिश कर रहा था, और मेरे उद्देश्यों के लिए मुझे केवल फ़ाइल नाम की आवश्यकता थी। मैंने पथ घटक को अलग करने की कोशिश की basename, लेकिन इसके साथ काम नहीं किया गया xargs:

$ find . -name '*.deb' -print | xargs basename 
basename: extra operand `./pool/main/a/aalib/libaa1_1.4p5-37+b1_i386.deb'
Try `basename --help' for more information.

मुझे इन दोनों में से एक ही चीज़ (बिल्कुल एक ही त्रुटि) मिलती है:

$ find . -name '*.deb' -print0 | xargs -0 basename 
$ find . -name '*.deb' -print | xargs basename {}

दूसरी ओर, यह उम्मीद के मुताबिक काम करता है:

$ find . -name '*.deb' -exec basename {} \;
foo
bar
baz

यह अप-टू-डेट साइगविन और डेबियन 5.0.3 पर होता है। मेरा निदान यह है कि xargs किसी कारण से दो इनपुट लाइनों को बेसनेम करने के लिए गुजर रहा है, लेकिन क्यों? यहाँ क्या चल रहा है?

जवाबों:


22

क्योंकि basenameसिर्फ एक पैरामीटर चाहता है ... बहुत नहीं। और xargsबहुत सारे पैरामीटर बनाता है।

अपनी वास्तविक समस्या को हल करने के लिए (केवल फ़ाइल नाम को सूचीबद्ध करें):

 find . -name '*.deb' -printf "%f\n"

कौन सा 'बस नाम' छापता है (आदमी ढूंढता है):

 %f     File's name with any leading directories
        removed (only the last element).

1
ऊह .... / थप्पड़ माथे फिर / मुझे लगता है कि मुझे "डमीज़ के लिए" पुस्तक की आवश्यकता है ...
quixote

मैंने सोचा था xargsकि इसका मतलब यह है कि यह तर्कों की एक सूची बनाता है और प्रत्येक को उस कमांड को खिलाता है जो बाद में आता है? अन्यथा उस और के बीच क्या अंतर है find . -name '*.deb' | basename?
विंडोजमेकर

GNU बेसन में अब एक -aविकल्प है: "कई तर्कों का समर्थन करें और प्रत्येक को एक नाम के रूप में समझें"।
बिशप

1
@ WindowsMaker कमांड तर्कों में xargsकनवर्ट करता stdinहै। एक तरह से, यह इसके विपरीत है echo, जो इसके तर्कों को परिवर्तित करता है stdout। के बीच अंतर find ... | xargs -n1 basenameया find ... | xargs basename -aऔर find ... | basenameहै कि पूर्व दो के कार्यान्वयन के साथ काम करेंगे है basenameकि उपेक्षा stdin
8bittree

18

इसे इस्तेमाल करे:

find . -name '*.deb' | xargs -n1 basename

यह स्पष्टीकरण नहीं है, यह एक समाधान है। और वर्कअराउंड के रूप में बस के रूप में 'बेसन' के माध्यम से किसी भी फ़ाइल के लिए -exec कॉलिंग के रूप में अच्छा है।
अकीरा

4
+1 ... जबकि स्पष्टीकरण नहीं है, इससे मुझे आपके द्वारा दिखाए जाने वाले xargs स्विच की जांच करने में मदद मिलेगी, जो अंततः मुझे माथे पर थप्पड़ मारने की गति की ओर ले जाएगा, मैं अभी अकीरा और जॉन टी के उत्तर
पढ़ता था

1
यह मेरा इसे करने का तरीका है। मुझे findकमांड के सभी ins और बहिष्कार सीखने का मन नहीं है , इसलिए मैं इसका उपयोग केवल फाइलों को खोजने और सूचीबद्ध करने के लिए करता हूं, और मैं हर चीज के लिए xargs का उपयोग करता हूं।
रयान थॉम्पसन

4

बेसन केवल एक तर्क को स्वीकार करता है। -execसही तरीके से कार्यों का उपयोग करना क्योंकि प्रत्येक {}को वर्तमान फ़ाइल नाम से संसाधित किया जा रहा है, और कमांड को एक बार मेल करने के बजाय, सभी तर्कों को एक बार में आधारभूत करने के लिए भेजने की कोशिश करने के बजाय मिलान फ़ाइल के अनुसार चलाया जाता है ।


2

xargs के रूप में अच्छी तरह से सिर्फ एक तर्क पारित करने के लिए मजबूर किया जा सकता है ...

find . -name '*.deb' -print | xargs -n1 basename

यह काम करता है, हालांकि स्वीकृत उत्तर findअधिक उपयुक्त तरीके से उपयोग कर रहा है। मुझे यह प्रश्न xargs basenameसमस्याओं के लिए खोज रहा है क्योंकि मैं फ़ाइल स्थानों की सूची प्राप्त करने के लिए किसी अन्य कमांड का उपयोग कर रहा हूं। -n1के लिए ध्वज xargsमेरे लिए अंतिम जवाब था।

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