कमांड आउटपुट के प्रत्येक लाइन में शेल कमांड कैसे लागू करें?


192

मान लीजिए कि मेरे पास कमांड से कुछ आउटपुट है (जैसे ls -1):

a
b
c
d
e
...

मैं echoप्रत्येक को एक कमांड (कहना ) लागू करना चाहता हूं , बदले में। उदाहरण के लिए

echo a
echo b
echo c
echo d
echo e
...

बैश में ऐसा करने का सबसे आसान तरीका क्या है?


3
ls -1यहां एक उदाहरण हो सकता है लेकिन यह याद रखना महत्वपूर्ण है कि इसके उत्पादन को पार्स करना अच्छा नहीं है ls। देखें: mywiki.wooledge.org/ParsingLs
codeforester

जवाबों:


217

इसका उपयोग करना शायद सबसे आसान है xargs। आपके मामले में:

ls -1 | xargs -L1 echo

-Lझंडा सुनिश्चित करता है इनपुट ठीक से पढ़ा जाता है। के मैन पेज से xargs:

-L number
    Call utility for every number non-empty lines read. 
    A line ending with a space continues to the next non-empty line. [...]

24
lsस्वचालित रूप -1से एक पाइप में करता है।
अगली सूचना तक रोक दिया गया।

5
@ डेनिस, ऐसा नहीं लगता है: ls | xargs -L2 echoऔर ls -1 | xargs -L2 echoदो अलग-अलग आउटपुट देते हैं। पूर्व सभी एक लाइन पर हैं।
एलेक्स बुडोव्स्की

2
@ एलेक्स: मुझे एक ही आउटपुट मिलता है।
अगली सूचना तक रोक दिया गया।

6
xargsकेवल निष्पादन योग्य फ़ाइलों को चला सकते हैं शेल फ़ंक्शन या शेल अंतर्निहित कमांड नहीं। पूर्व के लिए सबसे अच्छा समाधान शायद readएक लूप में एक है।
पाबौक

12
मैं चाहता हूं कि इस उत्तर में एक स्पष्टीकरण शामिल हो कि क्या -L1है।
वीक

163

आप प्रत्येक लाइन पर एक मूल प्रीपेंड ऑपरेशन का उपयोग कर सकते हैं:

ls -1 | while read line ; do echo $line ; done

या आप अधिक जटिल परिचालनों के लिए sed के लिए आउटपुट को पाइप कर सकते हैं:

ls -1 | sed 's/^\(.*\)$/echo \1/'

1
Sed कमांड काम नहीं करता है: sh: cho: not found a sh: cho: not foundऐसा लगता है कि यह eइको में ले रहा है एक sed कमांड या कुछ और।
एलेक्स बुडोव्स्की

whileलूप के लिए +1 । cmd1 | while read line; do cmd2 $line; done। या while read line; do cmd2 $line; done < <(cmd1)जो एक सबशेल नहीं बनाता है। यह आपकी sedकमांड का सरलीकृत संस्करण है :sed 's/.*/echo &/'
अगली सूचना तक रोक दिया गया।

1
@ एलेक्स: डबल कोट्स को सिंगल कोट्स में बदलें।
अगली सूचना तक रोक दिया गया।

5
"$line"शब्द विभाजन से बचने के लिए, जबकि लूप में उद्धरण दें ।
इग्निस

3
बच गए पात्रों के साथ खिलवाड़ read -r lineरोकने के लिए प्रयोग करके देखें read। उदाहरण के लिए echo '"a \"nested\" quote"' | while read line; do echo "$line"; doneदेता है "a "nested" quote", जो अपने भागने से हार गया है। अगर हम ऐसा echo '"a \"nested\" quote"' | while read -r line; do echo "$line"; doneकरने पर हम पाते "a \"nested\" quote"अपेक्षा के अनुरूप। Wiki.bash-hackers.org/commands/builtin/read
Warbo

9

आप लूप के लिए उपयोग कर सकते हैं :

फ़ाइल में * के लिए; करना
   गूंज "$ फ़ाइल"
किया हुआ

ध्यान दें कि यदि विचाराधीन कमांड कई तर्कों को स्वीकार करता है, तो xargs का उपयोग करना लगभग हमेशा अधिक कुशल होता है क्योंकि इसमें केवल कई बार के बजाय एक बार प्रश्न में उपयोगिता स्पॉन करना होता है।


1
यह xargs के उचित / सुरक्षित उपयोग का वर्णन करने के लायक है, अर्थात। printf '%s\0' * | xargs -0 ...- अन्यथा, यह व्हॉट्सएप, उद्धरण, आदि के साथ फ़ाइल नाम के साथ काफी असुरक्षित है
चार्ल्स डफी

8

आप वास्तव में इसे करने के लिए sed का उपयोग कर सकते हैं, बशर्ते वह GNU sed हो।

... | sed 's/match/command \0/e'

यह काम किस प्रकार करता है:

  1. कमांड मैच के साथ सब्स्टीट्यूट मैच
  2. प्रतिस्थापन निष्पादन आदेश पर
  3. प्रतिस्थापित आउटपुट को कमांड आउटपुट के साथ बदलें।

बहुत खुबस। मैं अंत में कमांड डालना भूल गया , लेकिन आपके जवाब को देखने के बाद ऐसा किया और इसने काम किया। मैं 1000 और 15000 के बीच एक यादृच्छिक आईडी को जोड़ने की कोशिश कर रहा था, जब SED एक लाइन से मेल खाती है। cat /logs/lfa/Modified.trace.log.20150904.pw | sed -r 's/^(.*)(\|006\|00032\|)(.*)$/echo "\1\2\3 - ID `shuf -i 999-14999 -n 1`"/e'
सग्गी

6
for s in `cmd`; do echo $s; done

यदि cmd में एक बड़ा आउटपुट है:

cmd | xargs -L1 echo

7
यदि cmdइसके आउटपुट में रिक्त स्थान हैं, तो पहला विफल हो जाएगा।
अगली सूचना तक रोक दिया गया।


2

xsgs बैकस्लैश, उद्धरण के साथ विफल रहता है। यह कुछ ऐसा होना चाहिए

ls -1 |tr \\n \\0 |xargs -0 -iTHIS echo "THIS is a file."

xargs -0 विकल्प:

-0, --null
          Input  items are terminated by a null character instead of by whitespace, and the quotes and backslash are
          not special (every character is taken literally).  Disables the end of file string, which is treated  like
          any  other argument.  Useful when input items might contain white space, quote marks, or backslashes.  The
          GNU find -print0 option produces input suitable for this mode.

ls -1आइटम को न्यूलाइन वर्णों के साथ समाप्त करता है, इसलिए trउन्हें शून्य वर्णों में अनुवाद करता है।

यह दृष्टिकोण मैन्युअल रूप से for ...( माइकल आरोन सफायन के उत्तर के साथ देखें ) की तुलना में लगभग 50 गुना धीमा है (3.55s बनाम 0.066%)। लेकिन अन्य इनपुट कमांड जैसे कि फ़ाइल से पता लगाना, ढूंढना, पढ़ना ( tr \\n \\0 <fileया इसी तरह), आपको xargsइस तरह से काम करना होगा।


1

मेरे लिए बेहतर परिणाम:

ls -1 | xargs -L1 -d "\n" CMD

बेहतर है, लेकिन सही नहीं है। find . -mindepth 1 -maxdepth 1 -print0 | xargs -0 commandउन मामलों को संभालेंगे जहां उत्पादन ls -1अस्पष्ट है; यदि आप प्रत्येक पर अग्रणी नहीं चाहते हैं तो -printf '%P\0'इसके बजाय उपयोग करें । -print0./
चार्ल्स डफी

1

मैं उदाहरण के लिए, एक सूची पर कई कमांड चलाने के लिए gawk का उपयोग करना पसंद करता हूं

ls -l | gawk '{system("/path/to/cmd.sh "$1)}'

हालांकि भागने वाले पात्रों के भागने से थोड़े बाल हो सकते हैं।

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