ढूँढें + xargs: तर्क रेखा बहुत लंबी है


21

मेरे पास निम्नलिखित की तरह एक पंक्ति है:

find /foo/bar -name '*.mp4' -print0 | xargs -i {} -0 mv -t /some/path {}

लेकिन मुझे निम्नलिखित त्रुटि मिली:

xargs: argument line too long

मैं उलझन में हूं। क्या xargsइस समस्या को ठीक करने में मदद नहीं की जानी चाहिए?

नोट: मुझे पता है कि मैं -execढूंढने में तकनीकी रूप से उपयोग कर सकता हूं , लेकिन मैं यह समझना चाहूंगा कि उपरोक्त क्यों विफल हो जाता है, क्योंकि मेरी समझ यह है कि xargsयह जानना चाहिए कि इनपुट को एक प्रबंधनीय आकार में उस तर्क को कैसे विभाजित किया जाए जो इसे चलाता है। क्या यह सच नहीं है?

यह सब zsh के साथ है।

जवाबों:


11

अच्छी तरह से एक चीज़ के लिए -iस्विच को हटा दिया जाता है:

-i[replace-str]
     This  option  is a synonym for -Ireplace-str if replace-str is specified. 
     If the replace-str argument is missing, the effect is the same as -I{}. 
     This option is deprecated; use -I instead.

इसलिए जब मैंने आपकी कमान इसके आसपास बदल दी, तो यह काम किया:

$ find /foo/bar -name '*.mp4' -print0 | xargs -I{} -0 mv -t /some/path {}

उदाहरण

$ find . -print0 | xargs -I{} -0 echo {}
.
./.sshmenu
./The GIT version control system.html
./.vim_SO
./.vim_SO/README.txt
./.vim_SO/.git
./.vim_SO/.git/objects
./.vim_SO/.git/objects/pack
./.vim_SO/.git/objects/pack/pack-42dbf7fe4a9b431a51da817ebf58cf69f5b7117b.idx
./.vim_SO/.git/objects/pack/pack-42dbf7fe4a9b431a51da817ebf58cf69f5b7117b.pack
./.vim_SO/.git/objects/info
./.vim_SO/.git/refs
./.vim_SO/.git/refs/tags
...

का उपयोग -I{}

इस कमांड निर्माण को चलाने के बाद से इस दृष्टिकोण का उपयोग नहीं किया जाना चाहिए:

$ find -print0 ... | xargs -I{} -0 ...

अंतर्निहित रूप से इन स्विचों को चालू करता है xargs, -xऔर -L 1-L 1कॉन्फ़िगर xargsइतना है कि यह आदेशों कॉल कर रहा है तो आप इसे एक भी फैशन में के माध्यम से फ़ाइलें चलाना चाहते हैं।

तो यह xargsयहाँ का उपयोग करने के उद्देश्य को हरा देता है क्योंकि यदि आप इसे 1000 फाइलें देते हैं तो यह mv1000 बार कमांड को चलाने वाला है ।

तो मुझे किस दृष्टिकोण का उपयोग करना चाहिए?

आप इसे इस तरह से xargs का उपयोग करके कर सकते हैं:

$ find /foot/bar/ -name '*.mp4' -print0 | xargs -0 mv -t /some/path

या बस यह सब करना है:

$ find /foot/bar/ -name '*.mp4' -exec mv -t /some/path {} +

धन्यवाद! जब आपने कहा कि तब "This approach shouldn't be used"किस दृष्टिकोण का उपयोग किया जाना चाहिए? चाहेंगे "find /foot/bar/ -name '*.csv' -print0 | xargs -0 mv -t some_dir'"एक बेहतर समाधान हो? यदि हां, तो कैसे करता है xargsजहां में इस मामले में पता mvतर्क यह पाइप से हो जाता है में फ़ीड करने के लिए आदेश? (क्या यह हमेशा उन्हें अंतिम स्थान पर रखता है?)
अमेलियो वाज़केज़-रीना

@ user815423426 - इसे केवल find ... -exec ...एक बेहतर तरीका है या यदि आप उपयोग करना चाहते हैं xargsतो find ... | xargs ... mv -t ...यह ठीक है। हाँ, यह हमेशा उन्हें पिछले डालता है। इसलिए उस तरीके की जरूरत है -t
स्लम

5

विकल्प -iएक वैकल्पिक तर्क लेता है। चूंकि आपने बाद में एक स्थान रखा -iथा, -iइसलिए विकल्प के लिए कोई तर्क नहीं था और इसलिए बाद -0में एक विकल्प नहीं था, xargsलेकिन 6 ऑपरेंड में से दूसरा {} -0 mv -t /some/path {}

केवल विकल्प के साथ -i, xargs ने फ़ाइल नामों की एक नई-अलग-अलग सूची की अपेक्षा की। चूँकि इनपुट में शायद कोई नई रेखा नहीं थी, xargs को एक विशाल फ़ाइल नाम जैसा दिखता था (एम्बेडेड नल बाइट्स के साथ, लेकिन xargs ने यह जाँच नहीं की)। यह एकल स्ट्रिंग जिसमें संपूर्ण आउटपुट findअधिकतम कमांड लाइन की लंबाई से अधिक था, इसलिए त्रुटि "कमांड लाइन बहुत लंबी है"।

आपकी आज्ञा के -i{}बजाय के साथ काम किया होता -i {}। वैकल्पिक रूप से, आप उपयोग कर सकते थे -I {}: -Iके समान है -i, लेकिन एक अनिवार्य तर्क लेता है, इसलिए इसे पास किए गए अगले तर्क xargsको -Iविकल्प के तर्क के रूप में उपयोग किया जाता है । फिर उसके बाद तर्क -0जो एक विकल्प के रूप में व्याख्या की जाती है, और इसी तरह।

हालाँकि, आपको बिल्कुल भी उपयोग नहीं करना चाहिए -I {}। उपयोग -Iके तीन प्रभाव हैं:

  • -Iउद्धरण प्रसंस्करण को बंद कर देता है, जो -0पहले से ही करता है।
  • -Iबदलने के लिए स्ट्रिंग को बदलता है, लेकिन {}डिफ़ॉल्ट मान है।
  • -Iप्रत्येक इनपुट रिकॉर्ड के लिए कमांड को अलग से निष्पादित करने का कारण बनता है, जो आपके आदेश ( mv -t) के बाद से बेकार है क्योंकि विशेष रूप से प्रति आह्वान के लिए कई फ़ाइलों का सामना करना पड़ता है।

या तो ड्रॉप -Iऔर -iपूरी तरह से

find /foo/bar -name '*.mp4' -print0 | xargs -0 mv -t /some/path {}

या xargs और उपयोग छोड़ें -exec:

find /foo/bar -name '*.mp4' -exec mv -t /some/path {} +

0

लूप के लिए एक बैश का उपयोग करने का प्रयास करें:

for FILE in *.mp4 ; do rm $FILE ; done

या यदि आप देखना चाहते हैं कि क्या हो रहा है:

for FILE in *.mp4 ; do echo Removing $FILE ; rm $FILE ; done

0

यदि आप मछली के खोल का उपयोग करते समय इसे देख रहे हैं ।
यह इस बात से संबंधित है कि मछली प्रतिस्थापन स्ट्रिंग का विस्तार कैसे करती है{}

यदि आप मछली का उपयोग कर रहे हैं तो आपको प्रतिस्थापन स्ट्रिंग से बचने की आवश्यकता है \{\}

| xargs -I \{\} echo \{\}

या एक अलग प्रतिस्थापन स्ट्रिंग का उपयोग करें

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