एक xargs कमांड में> कैसे उपयोग करें?


160

मैं एक bash कमांड ढूंढना चाहता हूं जो मुझे हर फाइल को एक डायरेक्टरी में grep करने देगा और उस grep के आउटपुट को एक अलग फाइल में लिखने देगा। मेरा अनुमान कुछ ऐसा करने का रहा होगा

ls -1 | xargs -I{} "grep ABC '{}' > '{}'.out"

लेकिन, जहाँ तक मुझे पता है, xargs को डबल-कोट्स पसंद नहीं हैं। यदि मैं दोहरे-उद्धरणों को हटा देता हूं, लेकिन तब कमांड पूरे कमांड के आउटपुट को एक {file} नामक एकल फ़ाइल में रीडायरेक्ट करती है, व्यक्तिगत फ़ाइलों की एक श्रृंखला के बजाय।

किसी को भी xargs का उपयोग करने का एक तरीका पता है? मैंने इस grep परिदृश्य का उपयोग एक उदाहरण के रूप में xargs के साथ अपनी समस्या को बताने के लिए किया है ताकि xargs का उपयोग न करने वाले कोई भी समाधान मेरे लिए लागू न हों।

जवाबों:


201

इसे करने की गलती न करें:

sh -c "grep ABC {} > {}.out"

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

xargs -I{} sh -c 'grep ABC "$1" > "$1.out"' -- {}

के xargsरूप में अच्छी तरह से लागू होता है find

वैसे, -0विकल्प के बिना कभी भी xargs का उपयोग न करें (जब तक कि बहुत दुर्लभ और नियंत्रित वन-टाइम इंटरैक्टिव उपयोग के लिए जहां आप अपने डेटा को नष्ट करने के बारे में चिंतित नहीं हैं)।

इसके अलावा पार्स न करें ls। कभी। ग्लोबिंग का उपयोग करें या findइसके बजाय:http://mywiki.wooledge.org/ParsingLs

findसब कुछ है कि एक और कुछ के लिए एक ग्लोब के साथ पुनरावृत्ति और एक सरल पाश की जरूरत के लिए उपयोग करें :

find /foo -exec sh -c 'grep "$1" > "$1.out"' -- {} \;

या गैर-पुनरावर्ती:

for file in *; do grep "$file" > "$file.out"; done

उद्धरणों के उचित उपयोग पर ध्यान दें।


अपवोट किया गया लेकिन संदेह पैदा हुआ। xargsबिना उपयोग नहीं -0: यह केवल तब लागू होता है जब आप findआउटपुट को xargsसही करते हैं? जब मैं यह करूँगा xargs -a <input_file>तो मैं इसका उपयोग कैसे करूँगा ? अधिकांश कमांड जैसे grepआउटपुट के साथ \nऔर न \0.ही एकमात्र तरीका जिसके बारे में मैं काम कर सकता हूं, वह यह है trकि शायद इसे ठीक करने के लिए फिर से उपयोग किया जाए। लेकिन केवल इसके साथ इसका उपयोग करना क्यों महत्वपूर्ण है -0?
लेजेंड्स 2k

3
@ किंवदंतियां 2k क्योंकि जब आप उपयोग नहीं करते हैं -0, xargsतो आपके फ़ाइल नाम ले लेंगे और उनमें सभी रिक्त स्थान, उद्धरण और बैकस्लैश तोड़ देंगे। आपको बस xargsएक उपकरण के रूप में भूलना चाहिए । यदि आपके पास लाइनें हैं, तो लाइनों को पुनरावृत्त करने के लिए एक बैश लूप का उपयोग करें: while read line; do <command> "$REPLY"; done < file-with-linesयाcommand | while ...
ल्यूनाथ

1
वाह, इस बारे में पता नहीं था, विस्तार के लिए धन्यवाद! इसलिए पोर्टेबिलिटी के लिए (चूंकि सभी xargsजीएनयू नहीं हैं), xargsइससे बचने की जरूरत है जब तक कि कोई इसका उपयोग न कर सके -0। धन्यवाद।
लीजेंड 2k

1
हालांकि मैं इस विशिष्ट उपयोग के मामले के लिए विस्तृत विवरण की सराहना करता हूं, लेकिन यह सवाल उत्पादन के पुनर्निर्देशन के बारे में है xargs, जिसमें हमेशा पार्सिंग lsया उपयोग करना शामिल नहीं है sh -c। यह सवाल का मामूली जवाब नहीं देता है, लेकिन सवाल का पहला Google परिणाम है, केवल भ्रम को जोड़ना।
pandasauce

1
@ इहानाथ, हाय, आपका जवाब मेरे लिए अच्छा है। लेकिन क्या आप इसके बारे में कुछ विस्तृत विवरण या लिंक दे सकते हैं xargs -I{} sh -c 'grep ABC "$1" > "$1.out"' -- {}? विशेष रूप से, अंत में एम्बेडेड (डबल) उद्धरण और "-" प्रतीक के नियम। धन्यवाद
स्कॉट यांग

40

इसके बिना एक समाधान xargsनिम्नलिखित है:

find . -mindepth 1 -maxdepth 1 -type f -exec sh -c "grep ABC '{}' > '{}.out'" \;

... और उसी के साथ किया जा सकता है xargs, यह पता चला है:

ls -1 | xargs -I {} sh -c "grep ABC '{}' > '{}.out'"

संपादित करें : एकल उद्धरण lhunath द्वारा टिप्पणी के बाद जोड़ा गया ।


उन्होंने कहा कि वे xargs का उपयोग करना चाहते हैं। मैंने इसके बिना भी एक समाधान पोस्ट किया है, लेकिन एक बार जब मैंने देखा कि उसे xargs की आवश्यकता है तो हटा दिया गया।
जिफ़्रे

आप सही हे। कारण मैंने अपना जवाब पोस्ट किया था कि किसी भी काम की तुलना में काम पाने के लिए वैकल्पिक समाधान रखना बेहतर है। पता चला कि इसने मुझे वांछित उत्तर (यानी, श-सी ट्रिक) खोजने के लिए सही रास्ते पर डाल दिया।
Stephan202 19

14

मैं मानता हूं कि आपका उदाहरण केवल एक उदाहरण है और आपको अन्य चीजों के लिए> आवश्यकता हो सकती है। GNU समानांतर http://www.gnu.org/software/parallel/ आपका बचाव हो सकता है। जब तक आपके फ़ाइल नाम में \ n नहीं है, तब तक उसे अतिरिक्त उद्धरण की आवश्यकता नहीं है:

ls | parallel "grep ABC {} > {}.out"

यदि आपके पास इसमें \ n फ़ाइल नाम है:

find . -print0 | parallel -0 "grep ABC {} > {}.out"

एक अतिरिक्त बोनस के रूप में आप नौकरियों को समानांतर में चलाते हैं।

अधिक जानने के लिए इंट्रो वीडियो देखें: http://pi.dk/1

10 सेकंड की स्थापना एक पूर्ण स्थापना करने की कोशिश करेगी; यदि वह विफल रहता है, तो एक व्यक्तिगत स्थापना; यदि वह विफल रहता है, तो एक न्यूनतम स्थापना:

$ (wget -O - pi.dk/3 || lynx -source pi.dk/3 || curl pi.dk/3/ || \
   fetch -o - http://pi.dk/3 ) > install.sh
$ sha1sum install.sh | grep 3374ec53bacb199b245af2dda86df6c9
12345678 3374ec53 bacb199b 245af2dd a86df6c9
$ md5sum install.sh | grep 029a9ac06e8b5bc6052eac57b2c3c9ca
029a9ac0 6e8b5bc6 052eac57 b2c3c9ca
$ sha512sum install.sh | grep f517006d9897747bed8a4694b1acba1b
40f53af6 9e20dae5 713ba06c f517006d 9897747b ed8a4694 b1acba1b 1464beb4
60055629 3f2356f3 3e9c4e3c 76e3f3af a9db4b32 bd33322b 975696fc e6b23cfb
$ bash install.sh

यदि आपको इसे सर्वर पर ले जाने की आवश्यकता है, जिसमें जीएनयू समानांतर स्थापित नहीं है, तो प्रयास करें parallel --embed

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