जब xargs की जरूरत है?


134

xargsआदेश हमेशा मुझे confuses। क्या इसके लिए एक सामान्य नियम है?

नीचे दो उदाहरणों पर विचार करें:

$ \ls | grep Cases | less

उन फाइलों को प्रिंट करता है जो 'केस' से मेल खाती हैं, लेकिन कमांड को बदलने की touchआवश्यकता होगी xargs:

$ \ls | grep Cases | touch
touch: missing file operand
Try `touch --help' for more information.

$ \ls | grep Cases | xargs touch

जवाबों:


143

अंतर यह है कि लक्ष्य कार्यक्रम किस डेटा को स्वीकार कर रहा है।

यदि आप बस एक पाइप का उपयोग करते हैं, तो यह डेटा के कच्चे ढेर के रूप में एसटीडीआईएन (मानक इनपुट स्ट्रीम) पर डेटा प्राप्त करता है जो एक समय में एक पंक्ति के माध्यम से सॉर्ट कर सकता है। हालाँकि कुछ कार्यक्रम मानक में उनकी आज्ञाओं को स्वीकार नहीं करते हैं, वे यह अपेक्षा करते हैं कि यह आदेशों के तर्कों के अनुसार किया जाएगा। उदाहरण के लिए touchकमांड लाइन पर एक पैरामीटर के रूप में एक फ़ाइल का नाम लेता है जैसे touch file1.txt:।

आप एक प्रोग्राम है जो फ़ाइल नाम आउटपुट है, तो बाहर मानक पर और उन्हें प्रयोग करना चाहते हैं तर्कों के रूप के लिए touch, आप का उपयोग करने के लिए है xargsजो STDIN धारा डेटा पढ़ता है और आदेश के लिए अंतरिक्ष अलग तर्क में प्रत्येक पंक्ति बदल देता है।

ये दो चीजें बराबर हैं:

# touch file1.txt
# echo file1.txt | xargs touch

का प्रयोग न करें xargsजब तक आप जानते हैं कि यह वास्तव में क्या कर रहा है और इसकी आवश्यकता क्यों है। यह अक्सर ऐसा होता है कि xargsरूपांतरण को लागू करने की तुलना में काम करने का एक बेहतर तरीका है । रूपांतरण प्रक्रिया भी संभावित नुकसान से बच रही है जैसे भागने और शब्द विस्तार आदि।


2
चेतावनी मुझे थोड़ी सख्त लगती है। कमांड लाइन ( xargsऔर $(...)) पर एक स्ट्रीम प्राप्त करने के लिए दो सामान्य विकल्पों में से , xargs कमांड प्रतिस्थापन से कहीं अधिक सुरक्षित है। और मैं कभी भी इसमें एक नई रेखा के साथ एक वैध फ़ाइल नाम याद नहीं कर सकता। भागने और शब्द विस्तार के मुद्दे कमांड प्रतिस्थापन के साथ नहीं हैं, न कि xargs?
२१:३१ बजे कैम

6
@camh: वे दोनों के साथ संभावित नुकसान कर रहे हैं। शेल में, आपको फ़ाइलनामों के बारे में चिंता करनी होगी जो रिक्त स्थान, टैब और नईलाइन पर विभाजित हो रहे हैं। Xargs में, आपको केवल newlines के बारे में चिंता करनी होगी। Xargs में, यदि आप आउटपुट ठीक से स्वरूपित करते हैं, तो आप इसके बजाय NUL वर्ण ( xargs -0) पर शब्दों / फ़ाइलनामों को विभाजित कर सकते हैं , जो कि साथ में उपयोगी है find -print0
केन ब्लूम

क्या xargsप्रोग्राम को शेल के माध्यम से अंतरिक्ष में अलग-अलग आर्ग के साथ कॉल किया जाता है, या क्या यह वास्तव में आंतरिक रूप से तर्क सूची का निर्माण करता है (जैसे execv/ के साथ उपयोग के लिए execp)?
detly

1
यह आंतरिक रूप से इसका निर्माण करता है और निष्कासन का उपयोग करता है, इसलिए यह सुरक्षित है। इसके अलावा, GNU xargs (जैसा कि लिनक्स और कुछ अन्य पर प्रयोग किया जाता है) आपको अपने परिसीमन के रूप में नई रेखा निर्दिष्ट करने देता है -d \n, हालाँकि BSD xargs (OSX et al) इस विकल्प का समर्थन नहीं करता है।
शराबी

72

पहले से दिए गए उत्तरों पर विस्तार करने के लिए, xargsएक शांत काम कर सकते हैं जो आज के मल्टीकोर और वितरित कंप्यूटिंग परिदृश्य में महत्वपूर्ण होता जा रहा है: यह निर्माण कार्यों को रोक सकता है।

उदाहरण के लिए:

$ find . -type f -name '*.wav' -print0 |xargs -0 -P 3 -n 1 flac -V8

एक बार में तीन प्रक्रियाओं का उपयोग करते हुए * .wav => * .flac को एनकोड करेंगे ( -P 3)।


वाह। मुझे यह एक सप्ताह पहले पता होना चाहिए था जब मैं 50GiB WAVs के साथ बिल्कुल वैसा ही काम कर रहा था (OGG को छोड़कर)। :)
एलोइस महदाल

क्यों नहीं -exec पैरामीटर का उपयोग करें जो मिल गया है?
एवगेनी

3
@Evgeny -execपैरामीटर समांतर-प्रक्रिया कार्य नहीं करेगा।
एम्फेटामैचिन

यह नोट करने के लिए अच्छा है कि यह -0तर्कxargs देता है कि यह NULLचरित्र को इनपुट आइटम परिसीमन मानता है। find -print0आउटपुट NULL- सीमांकित आइटम। यह फ़ाइल नाम के लिए बहुत अच्छा अभ्यास है जिसमें रिक्त स्थान, उद्धरण या अन्य विशेष वर्ण शामिल हो सकते हैं।
डैन डस्केल्सस्कू

24

xargs विशेष रूप से तब उपयोगी होता है जब आपके पास स्टडिन पर फ़ाइलपथ की सूची होती है और उनके साथ कुछ करना चाहते हैं। उदाहरण के लिए:

$ git ls-files "*.tex" | xargs -n 1 sed -i "s/color/colour/g"

आइए इस कदम की जाँच करें:

$ git ls-files "*.tex"
tex/ch1/intro.tex
tex/ch1/motivation.tex
....

दूसरे शब्दों में, हमारा इनपुट उन रास्तों की सूची है, जिन्हें हम कुछ करना चाहते हैं।

इन रास्तों से xargs क्या करता है, यह जानने के लिए, echoआपकी आज्ञा से पहले एक अच्छी चाल जोड़ी जानी चाहिए , जैसे:

$ git ls-files "*.tex" | xargs -n 1 echo sed -i "s/color/colour/g"
sed -i "s/color/colour/g" tex/ch1/intro.tex
sed -i "s/color/colour/g" tex/ch1/motivation.tex
....

-n 1तर्क xargs अपने आप में एक आदेश में प्रत्येक पंक्ति बारी कर देगा। sed -i "s/color/colour/g"आदेश की सभी घटनाओं का स्थान ले लेगा colorसाथ colourनिर्दिष्ट फ़ाइल के लिए।

ध्यान दें कि यह केवल तभी काम करता है जब आपके रास्तों में कोई स्थान न हो। यदि आप करते हैं, तो आपको -0ध्वज को पास करके xargs में इनपुट के रूप में अशक्त समाप्ति पथ का उपयोग करना चाहिए । एक उदाहरण उपयोग होगा:

$ git ls-files -z "*.tex" | xargs -0 -n 1 sed -i "s/color/colour/g"

जो जैसा हमने ऊपर वर्णित किया है, वैसा ही होता है, लेकिन यह भी काम करता है कि क्या किसी एक पथ में एक स्थान है।

यह किसी भी कमांड के साथ काम करता है जो उत्पादन के रूप में फाइलनेम का उत्पादन करता है जैसे findया locate। यदि आप इसे बहुत सारी फ़ाइलों के साथ गिट रिपॉजिटरी में उपयोग करने के लिए करते हैं, हालांकि, इसके git grep -lबजाय इसका उपयोग करना अधिक कुशल हो सकता है git ls-files, जैसे:

$ git grep -l "color" "*.tex" | xargs -n 1 sed -i "s/color/colour/g"

git grep -l "color" "*.tex"आदेश "* .tex" वाक्यांश "रंग" वाली फ़ाइलों की एक सूची दे देंगे।


1
यह सच है, लेकिन अगर आपने इसे सीख लिया है तो आपको यह भी सीखना चाहिए कि खोज के खराब अभ्यास के कारण लूपिंग क्यों है?
वाइल्डकार्ड

6

आपका पहला तर्क अंतर को अच्छी तरह दिखाता है।

\ls | grep Cases | lessआपको lsऔर द्वारा निर्मित फ़ाइल नामों की सूची ब्राउज़ करने देता है grep। इससे कोई फर्क नहीं पड़ता कि वे फ़ाइल नाम हैं, वे सिर्फ कुछ पाठ हैं।

\ls | grep Cases | xargs lessआप उन फ़ाइलों को ब्राउज़ कर सकते हैं जिनके नाम कमांड के पहले भाग द्वारा निर्मित हैं। xargsइनपुट और उसके कमांड लाइन पर एक कमांड के रूप में फ़ाइल नामों की सूची लेता है, और पर फ़ाइल नाम के साथ आदेश चलाता है अपने कमांड लाइन।

उपयोग करने पर विचार करते समय xargs, ध्यान रखें कि यह एक अजीब तरीके से तैयार किए गए इनपुट की अपेक्षा करता है: व्हाट्सएप-सीमांकित, के साथ \, 'और "उद्धरण के लिए उपयोग किया जाता है (एक असामान्य तरीके से, क्योंकि \विशेष उद्धरण के अंदर नहीं है)। केवल तभी उपयोग करें xargsजब आपके फ़ाइल नाम में व्हॉट्सएप न हो या \'"


@ गिल्स: रिक्त स्थान के मुद्दे के आसपास जाने xargsका -0, --nullविकल्प है (यह अत्यधिक संभावना है कि मैंने आपसे सीखा है :), इसलिए मैं मानता हूं कि आप एक नो-ऑप्शन xargकॉल की बात कर रहे हैं , लेकिन मैं आपके उद्धरण के संदर्भ से हैरान हूं। क्या आपके पास उसके बारे में एक लिंक या एक उदाहरण है? .. (ps। | xargs lessएक आसान "ट्रिक" +1 है .. धन्यवाद ..
पीटर।

4

अपने उदाहरण में आपको बिल्कुल भी उपयोग करने की आवश्यकता नहीं है xargsक्योंकि findआप जो करना चाहते हैं वह ठीक और सुरक्षित रूप से करेंगे।

वास्तव में आप क्या उपयोग करना चाहते हैं find:

find -maxdepth 1 -name '*Cases*' -exec touch {} +

इस उदाहरण में -maxdepth 1इसका मतलब है कि केवल वर्तमान निर्देशिका में खोज करें, किसी भी उपनिर्देशिका में न उतरें; डिफ़ॉल्ट रूप से सभी उपनिर्देशिकाओं (जो अक्सर आप चाहते हैं) में देखेंगे जब तक कि आप इसे मैक्सडेपथ के साथ बाधित नहीं करते। {}फ़ाइल को उसके स्थान पर प्रतिस्थापित हो जाएगी और का नाम है +दो अंत के आदेश मार्करों में से एक, अन्य से किया जा रहा है ;। उनके बीच का अंतर यह है कि ;प्रत्येक फ़ाइल पर कमांड को एक बार में +निष्पादित करें , जबकि इसका मतलब है कि एक साथ सभी फाइलों पर कमांड निष्पादित करें। ध्यान दें, हालांकि, आपका शेल संभवतः ;खुद को व्याख्या करने की कोशिश करेगा , इसलिए आपको इसे \;या तो साथ भागने की आवश्यकता होगी ';'। हां, findइस तरह की बहुत कम झुंझलाहट है, लेकिन इसकी शक्ति इसके लिए अधिक से अधिक है।

दोनों findऔर xargsपहली बार में जानने के लिए मुश्किल कर रहे हैं। आपको xargsउस विकल्प -pया --interactiveविकल्प का उपयोग करके सीखने में मदद करने के लिए जो आपको वह कमांड दिखाएगा जिसके बारे में वह आपको निष्पादित करना और संकेत देना चाहता है कि आप इसे चलाना चाहते हैं या नहीं।

इसी तरह से findआप कमांड चलाने के लिए या न चाहते हुए भी आपको संकेत देने के -okस्थान पर उपयोग कर सकते हैं -exec

हालांकि, ऐसे समय होते हैं, जब findआप वह सब कुछ नहीं कर पाएंगे जो आप चाहते हैं और वह वह जगह है जहाँ पर xargsआता है। -execकमांड केवल एक ही उदाहरण को स्वीकार करेगा {}, इसलिए यदि आपको कोई त्रुटि मिलती है find -type f -exec cp {} {}.bak \;तो आप इसके बजाय ऐसा कर सकते हैं। :find -type f -print0 | xargs -0 -l1 -IX cp X X.bak

आप GNU Findutils मैनुअल में रन कमांड के बारे में अधिक जान सकते हैं ।

इसके अलावा, मैंने उल्लेख किया है कि findसुरक्षित रूप से आप क्या चाहते हैं क्योंकि जब आप फ़ाइलों के साथ काम कर रहे हैं तो आप रिक्त स्थान और अन्य वर्णों के साथ जा रहे हैं जो xargsतब तक समस्या पैदा करेगा जब तक कि आप -0या --nullविकल्प के साथ कुछ का उपयोग न करें जो कि एक अशक्त चरित्र द्वारा समाप्त इनपुट आइटम उत्पन्न करता है। व्हॉट्सएप का।



@Wildcard फ़ाइल नाम के साथ रिक्त स्थान या वर्ण जैसे कि 'या "समस्याग्रस्त हो सकते हैं, जबकि findउन मामलों को बिना किसी समस्या के संभाल लेंगे।
aculich

हाँ मैं जानता हूँ। जुड़े प्रश्न के लिए मेरा जवाब देखें । मुझे संभवतः उस प्रश्न को उपरोक्त टिप्पणी में एक बयान में देना चाहिए, या उसके सामने "प्रश्न देखें ..." वाक्यांश जोड़ा। : D
वाइल्डकार्ड

1

xargs(साथ साथ find, sort, du, uniq, perlऔर कुछ अन्य लोगों) को कहते हैं "STDIN फ़ाइलों की एक सूची, एक NUL (0x00) बाइट से अलग कर दिया गया है" एक कमांड लाइन स्विच स्वीकार करता है। इससे रिक्त स्थान और उन में अन्य मजाकिया पात्रों के साथ फ़ाइल नाम को संभालना आसान हो जाता है। फ़ाइल नाम में NUL नहीं होते हैं।


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