कटौती तुच्छ लेकिन अयोग्य जवाब बंद करने के लिए सबसे पहले: मैं न तो उपयोग कर सकते हैं find
+ xargs
चाल और न ही उसके संस्करण (जैसे find
के साथ -exec
), क्योंकि मैं प्रति कॉल कुछ इस तरह के एक्सप्रेशन का उपयोग करने की जरूरत है। मैं अंत में इस पर वापस आऊंगा।
अब एक बेहतर उदाहरण के लिए आइए विचार करें:
$ find -L some/dir -name \*.abc | sort
some/dir/1.abc
some/dir/2.abc
some/dir/a space.abc
मैं उन लोगों को तर्क के रूप में कैसे पास करूं program
?
बस कर यह चाल नहीं है
$ ./program $(find -L some/dir -name \*.abc | sort)
program
निम्नलिखित तर्क मिलने के बाद विफल रहता है:
[0]: ./program
[1]: some/dir/1.abc
[2]: some/dir/2.abc
[3]: some/dir/a
[4]: space.abc
जैसा कि देखा जा सकता है, अंतरिक्ष के साथ पथ विभाजित था और program
इसे दो अलग-अलग तर्क मानता है।
काम होने तक बोली
ऐसा लगता है कि नौसिखिए उपयोगकर्ता अपने आप को, जब ऐसी समस्याओं का सामना करते हैं, तब तक बेतरतीब ढंग से उद्धरण जोड़ते हैं जब तक कि यह अंत में काम नहीं करता - केवल यहाँ यह मदद करने के लिए प्रतीत नहीं होता है ...
"$(…)"
$ ./program "$(find -L some/dir -name \*.abc | sort)"
[0]: ./program
[1]: some/dir/1.abc
some/dir/2.abc
some/dir/a space.abc
क्योंकि उद्धरण शब्द-विभाजन को रोकते हैं, सभी फाइलें एक ही तर्क के रूप में पारित की जाती हैं।
अलग-अलग रास्तों का हवाला देते हुए
एक आशाजनक दृष्टिकोण:
$ ./program $(find -L some/dir -name \*.abc -printf '"%p"\n' | sort)
[1]: "some/dir/1.abc"
[2]: "some/dir/2.abc"
[3]: "some/dir/a
[4]: space.abc"
उद्धरण हैं, सुनिश्चित करें। लेकिन अब उनकी व्याख्या नहीं है। वे तार का हिस्सा हैं। इसलिए न केवल उन्होंने शब्द विभाजन को नहीं रोका, बल्कि वे बहस में पड़ गए!
IFS बदलें
फिर मैंने साथ खेलने की कोशिश की IFS
। मैं पसंद करेंगे find
के साथ -print0
और sort
साथ -z
वैसे भी - इतना है कि वे "वायर्ड पथ" खुद पर कोई मुद्दों होगा। तो क्यों नहीं null
चरित्र पर शब्द बंटवारे और यह सब किया है?
$ ./program $(IFS=$'\0' find -L some/dir -name \*.abc -print0 | sort -z)
[0]: ./program
[1]: some/dir/1.abcsome/dir/2.abcsome/dir/a
[2]: space.abc
तो यह अभी भी अंतरिक्ष पर बंटता है और पर विभाजित नहीं होता है null
।
मैंने IFS
असाइनमेंट को $(…)
(जैसा कि ऊपर दिखाया गया है) और उससे पहले दोनों जगह रखने की कोशिश की ./program
। इसके अलावा, मैं अन्य वाक्य रचना की कोशिश की तरह \0
, \x0
, \x00
दोनों के साथ उद्धृत किया '
और "
के साथ या बिना के रूप में भी $
। उन लोगों में से कोई भी कोई फर्क नहीं लग रहा था ...
और यहाँ मैं विचारों से बाहर हूँ। मैंने कुछ और चीजों की कोशिश की, लेकिन सभी को सूचीबद्ध करने के लिए नीचे की समस्याओं की तरह लग रहा था।
इसके अलावा मेरे द्वारा और क्या किया जा सकता है? क्या यह सब करने योग्य है?
ज़रूर, मैं program
पैटर्न को स्वीकार कर सकता हूं और खुद खोज कर सकता हूं । लेकिन एक विशिष्ट सिंटैक्स के लिए इसे ठीक करते समय यह बहुत दोहरा काम है। ( grep
उदाहरण के लिए फाइलें उपलब्ध कराने के बारे में क्या ?)।
इसके अलावा, मैं program
पथों की सूची के साथ फ़ाइल को स्वीकार कर सकता हूं । तब मैं आसानी find
से कुछ अस्थायी फ़ाइल में अभिव्यक्ति डंप कर सकता हूं और केवल उस फ़ाइल को पथ प्रदान कर सकता हूं । इसका समर्थन प्रत्यक्ष रास्तों के साथ किया जा सकता है ताकि यदि उपयोगकर्ता के पास एक सरल मार्ग है तो उसे बिना मध्यवर्ती फ़ाइल के प्रदान किया जा सके। लेकिन यह अच्छा नहीं लगता है - किसी को अतिरिक्त फ़ाइलों का निर्माण करने की आवश्यकता है और अतिरिक्त देखभाल का उल्लेख नहीं करना है। (प्लस साइड पर, हालांकि, यह उन मामलों के लिए बचाव हो सकता है जिनमें तर्कों के रूप में फाइलों की संख्या कमांड लाइन की लंबाई के साथ मुद्दों का कारण बनने लगती है ...)
अंत में, मैं आपको फिर से याद दिला दूं कि find
+ xargs
(और एक जैसे) ट्रिक्स मेरे मामले में काम नहीं करेंगे। विवरण सादगी के लिए मैं केवल एक तर्क दिखा रहा हूं। लेकिन मेरा असली मामला इस तरह दिखता है:
$ ABC_FILES=$(find -L some/dir -name \*.abc | sort)
$ XYZ_FILES=$(find -L other/dir -name \*.xyz | sort)
$ ./program --abc-files $ABC_FILES --xyz-files $XYZ_FILES
तो xargs
एक खोज से कर मुझे अभी भी कैसे दूसरे के साथ सौदा करने के लिए छोड़ देता है ...
mapfile
(या इसके पर्यायवाचीreadarray
) पर कुछ नहीं मिला । लेकिन यह काम करता है!