2015-03-26 5 views
6

मैं एक कमांड जो फ़ाइलों के लिए UUIDs उत्पन्न करने के लिए प्रयास कर रहा है है:क्या प्रत्येक तर्क के लिए xargs एक सबहेल कमांड निष्पादित कर सकते हैं?

find -printf "%P\n"|sort|xargs -L 1 echo $(uuid) 

लेकिन परिणाम में, xargs केवल $(uuid) subshell एक बार निष्पादित हो रहा है:

8aa9e7cc-d3b2-11e4-83a6-1ff1acc22a7e file1 
8aa9e7cc-d3b2-11e4-83a6-1ff1acc22a7e file2 
8aa9e7cc-d3b2-11e4-83a6-1ff1acc22a7e file3 

वहाँ एक एक लाइनर (है यानी कोई फंक्शन नहीं) प्रत्येक इनपुट पर सबहेल कमांड निष्पादित करने के लिए xargs प्राप्त करने के लिए?

+1

@TomFenech: '-n 1' वास्तव में किसी भी खाली स्थान के आधार पर विभाजित हैं, चाहे लाइन आंतरिक या नहीं, तो आदेश एम्बेडेड व्हाइटस्पेस के साथ पथ के साथ तोड़ देगा; '-L 1' इरादे के करीब आता है, जिसमें यह लाइन-बाय-लाइन प्रोसेसिंग करता है, लेकिन प्रत्येक पंक्ति पर शब्द-विभाजन अभी भी लागू होता है, ताकि संभावित रूप से _multiple_ तर्क प्रति इनपुट लाइन 'echo'' (जो हो सकता है) या समस्या का कारण नहीं हो सकता है)। मजबूत दृष्टिकोण '-I' का उपयोग स्वीकार किए गए उत्तर में करना है। – mklement0

उत्तर

10

ऐसा इसलिए है क्योंकि $(uuid) वर्तमान खोल में विस्तारित हो जाता है। xargs बिना

find -exec bash -c 'echo "$(uuid) ${1#./}"' -- '{}' \; 

: Btw

find -printf "%P\n"| sort | xargs -I '{}' bash -c 'echo $(uuid) {}' 

, मैं निम्न आदेश का उपयोग होगा: आप स्पष्ट रूप से एक खोल कह सकते हैं।

+2

अच्छी तरह से किया; लेकिन न केवल '-n 1' अनिवार्य है, क्योंकि' -I' लाइन-बाय-लाइन प्रोसेसिंग का तात्पर्य है, '-एन 1' वास्तव में _any_ व्हाइटस्पेस द्वारा विभाजित होगा, चाहे लाइन-इंटीरियर या नहीं। जबकि -एल 1' लाइन-बाय-लाइन प्रोसेसिंग करता है, शब्द-विभाजन अभी भी प्रत्येक पंक्ति पर लागू होता है, जबकि '-I' पूरी लाइन को _single_ तर्क के रूप में मानता है। – mklement0

+1

@ mklement0 इसे इंगित करने के लिए धन्यवाद! संपादित किया गया है कि – hek2mgl

2

पाश के लिए एक साथ :

for i in $(find -printf "%P\n" | sort) ; do echo "$(uuid) $i"; done 

संपादित करें: यह करने के लिए एक और तरीका:

find -printf "%P\0" -exec uuid -v 4 \; | sort | awk -F'\0' '{ print $2 " " $1}' 

इस फ़ाइल नाम UUID के बाद आउटपुट (कोई subshell) की आवश्यकता सॉर्ट होने के लिए, फिर दो स्तंभों को शून्य से अलग कर देता है।

+0

यह भी काम करता है और पढ़ने के लिए थोड़ा आसान संस्करण है और साथ ही साथ प्रत्येक तर्क पर एक नए बैश के ऊपर की ओर नहीं है। अगर मैं क्रेडिट विभाजित कर सकता हूं, तो मैं चाहता हूं। धन्यवाद। – adelphus

+0

इस उदाहरण में एक शेल लूप का उपयोग प्रदर्शन कारणों के लिए एक अच्छा विचार है, लेकिन 'while' लूप का उपयोग करना बेहतर है, क्योंकि' for' एम्बेडेड रिक्त स्थान वाले फ़ाइल नामों के साथ तोड़ देगा, उदाहरण के लिए - http: //mywiki.wooledge देखें .org/DontReadLinesWithFor – mklement0

+1

@ mklement0 यह बहुत सच धन्यवाद है; वैसे भी मैंने यह तय किया कि लूप को छोड़ना बेहतर है –

2

hek2mgl's answer समस्या को अच्छी तरह से बताता है और उसका समाधान अच्छी तरह से काम करता है; यह उत्तर प्रदर्शन पर दिखता है।

स्वीकृत उत्तर एक छोटा धीमा है, क्योंकि यह प्रत्येक इनपुट लाइन के लिए bash प्रक्रिया बनाता है। जबकि

xargs कारण है कि शेल कार्यक्षमता प्रत्येक चरण में की जरूरत है आम तौर पर के लिए बेहतर और एक खोल-कोड पाश की तुलना में तेजी है, इस विशेष मामले में भूमिकाओं उलट कर रहे हैं,।

निम्नलिखित वैकल्पिक समाधान इनपुट लाइनों प्रक्रिया पूरी होने में while पाश का उपयोग करता है, और, मेरे मशीन पर, के बारे में दोगुनी गति सेxargs समाधान के रूप में है।

find . -printf "%P\n" | sort | while IFS= read -r f; do echo "$(uuid) $f"; done 
  • नोट while बजाय for का उपयोग करते हैं, क्योंकि for मजबूती के साथ आदेश उत्पादन पार्स नहीं कर सकता (संक्षेप में: एम्बेडेड सफेद स्थान के साथ फ़ाइल नाम आदेश टूट जाएगा - http://mywiki.wooledge.org/DontReadLinesWithFor देखें)।

आप एम्बेडेड नई-पंक्तियों (कम ही है) के साथ फ़ाइल नामों को लेकर चिंतित हैं और जीएनयू उपयोगिताओं का उपयोग करते हैं, तो आप विभाजक के रूप में NUL बाइट्स इस्तेमाल कर सकते हैं:

find . -printf "%P\0" | sort -z | while IFS= read -d '' -r f; do echo "$(uuid) $f"; done 

अद्यतन: सबसे तेज़ दृष्टिकोण एक शेल लूप का उपयोग नहीं करना है, जैसा कि ᴳᵁᴵᴰᴼ's clever answer से प्रमाणित है। उसके उत्तर के पोर्टेबल संस्करण के लिए नीचे देखें।


संगतता ध्यान दें:

ओपी के find आदेश के उपयोग जीएनयूfind (लिनक्स) का अर्थ है, और सुविधाओं (-printf) का उपयोग करता है और प्लेटफार्म पर काम न करें।

यहाँ ᴳᵁᴵᴰᴼ's answerfind (और awk) का केवल POSIX अनुरूप सुविधाओं का उपयोग करता है की एक पोर्टेबल संस्करण है।
नोट, हालांकि, uuid एक पॉज़िक्स उपयोगिता नहीं है; के बाद से Linux और BSD जैसी प्रणालियों (सहित OSX) एक uuidgen उपयोगिता है, तो कमांड का उपयोग करता है बजाय कि:

find . -exec printf '%s\t' {} \; -exec uuidgen \; | 
    awk -F '\t' '{ sub(/.+\//,"", $1); print $2, $1 }' | sort -k2 
संबंधित मुद्दे