न्यूमेरिकल ऑर्डर के साथ ग्लोब


27

मेरे पास एक निर्देशिका में पीडीएफ फाइलों की यह सूची है:

c0.pdf   c12.pdf  c15.pdf  c18.pdf  c20.pdf  c4.pdf  c7.pdf
c10.pdf  c13.pdf  c16.pdf  c19.pdf  c2.pdf   c5.pdf  c8.pdf
c11.pdf  c14.pdf  c17.pdf  c1.pdf   c3.pdf   c6.pdf  c9.pdf

मैं संख्यात्मक क्रम में भूत-विद्या का उपयोग करके इन्हें समाहित करना चाहता हूं (इसके समान):

gs -q -sPAPERSIZE=a4 -dNOPAUSE -dBATCH -sDEVICE=pdfwrite -sOutputFile=out.pdf *.pdf

लेकिन शेल विस्तार क्रम संख्याओं के प्राकृतिक क्रम को नहीं बल्कि वर्णानुक्रम क्रम को पुन: उत्पन्न करता है:

$ for f in *.pdf; do echo $f; done
c0.pdf
c10.pdf
c11.pdf
c12.pdf
c13.pdf
c14.pdf
c15.pdf
c16.pdf
c17.pdf
c18.pdf
c19.pdf
c1.pdf
c20.pdf
c2.pdf
c3.pdf
c4.pdf
c5.pdf
c6.pdf
c7.pdf
c8.pdf
c9.pdf

मैं विस्तार में वांछित आदेश कैसे प्राप्त कर सकता हूं (यदि 0फ़ाइल नामों में संख्याओं को मैन्युअल रूप से जोड़ने के बिना संभव है )?

मुझे उपयोग करने के लिए सुझाव मिले हैं ls | sort -V, लेकिन मैं इसे अपने विशिष्ट उपयोग के मामले में काम नहीं कर पाया ।


आप सभी मामलों में केवल दो अंकों की संख्या का उपयोग कर सकते हैं , इसलिए वर्णानुक्रम क्रम संख्यात्मक क्रम से मेल खाएगा। जब तक आप चीजों को कठिन तरीके से नहीं करना चाहते हैं।
वाइल्डकार्ड

1
3 अंकों की संख्या, कम से कम! Y2K याद रखें।
22

जवाबों:


12

अपने पर्यावरण के आधार पर आप ls -vGNU कोरुटिल्स के साथ उपयोग कर सकते हैं , जैसे:

gs -q -sPAPERSIZE=a4 -dNOPAUSE -dBATCH -sDEVICE=pdfwrite \
   -sOutputFile=out.pdf $(ls -v)

या यदि आप FreeBSD या OpenBSD के हाल के संस्करणों पर हैं:

gs -q -sPAPERSIZE=a4 -dNOPAUSE -dBATCH -sDEVICE=pdfwrite \
   -sOutputFile=out.pdf $(ls | sort -V)

ls -vहोगा natural sort of (version) numbers within textतो यह है कि अच्छी तरह से इस्तेमाल किया जा सकता ...
संदीप

@ संदीप: वास्तव में, लेकिन यह केवल समाधान के लिए एक जीएनयू कोर्यूटिल्स लगता है।
थोर

हाँ, GNU विशिष्ट जैसा लगता है - pubs.opengroup.org/onlinepubs/9699919799
Sundeep

1
@ सुदीप: की -Vसुविधा sortPOSIX द्वारा निर्दिष्ट नहीं है। हालांकि, ऐसा लगता है कि यह फैल गया है, उदाहरण के लिए FreeBSD और OpenBSD दोनों sortइसका समर्थन करते हैं।
थोर

ओह ठीक है, क्या आप इन विवरणों को उत्तर देने के लिए जोड़ सकते हैं? मैं इसी तरह की समस्या (संख्यात्मक क्रम में ग्लोब) की खोज करते हुए इस उत्तर में आया था और lsमैंने देखा कि अगर इसमें पाइपिंग के बजाय छँटाई करने के बजाय खुद ही विकल्प होता है :)
Sundeep


12

यदि प्रश्न की सभी फाइलों में एक ही उपसर्ग है (यानी, संख्या से पहले पाठ; cइस मामले में), तो आप उपयोग कर सकते हैं

gs   … args…   c? .pdf c ??। pdf

c?.pdfफैलता है c0.pdf c1.pdfc9.pdf।  c??.pdfकरने के लिए फैलता है c10.pdf c11.pdf... c20.pdf (और अप करने के लिए c99.pdf, लागू के रूप में)। हालांकि प्रत्येक कमांड-लाइन शब्द जिसमें पाथनेम एक्सपेंशन कैरेक्टर (एस) है LC_COLLATE, वैरिएबल के अनुसार सॉर्ट किए गए (मिलाए गए) फ़ाइलनामों की सूची में विस्तारित है, आसन्न वाइल्डकार्ड्स (ग्लब्स) के विस्तार से उत्पन्न सूचियों को विलय नहीं किया जाता है; वे बस संक्षिप्त कर रहे हैं। (मुझे याद है कि शेल मैन पेज ने एक बार यह स्पष्ट रूप से कहा था, लेकिन मैं इसे अब नहीं खोज सकता।)

बेशक अगर फाइलें ऊपर जा सकती हैं c999.pdf, तो आपको उपयोग करना चाहिए c?.pdf c??.pdf c???.pdf। यदि आपके पास बहुत सारे अंक हैं, तो जाहिर है, यह थकाऊ हो सकता है। आप इसे थोड़ा संक्षिप्त कर सकते हैं; उदाहरण के लिए, (पांच अंकों तक), आप उपयोग कर सकते हैं c?{,?{,?{,?{,?}}}}.pdf। यदि आपकी फ़ाइल नाम की सूची विरल है (उदाहरण के लिए, वहाँ c0.pdfएक है c12345.pdf, लेकिन जरूरी नहीं कि बीच में हर संख्या हो), तो आपको शायद nullglobविकल्प निर्धारित करना चाहिए । अन्यथा, यदि (उदाहरण के लिए) आपके पास दो अंकों की संख्या वाली कोई फाइल नहीं है, तो आपको c??.pdfअपने कार्यक्रम के लिए शाब्दिक तर्क मिलेगा ।

आप एक से अधिक उपसर्ग (जैसे, है, तो , है, और , एक या दो अंकों की संख्या के साथ), तो आपको स्पष्ट है, जानवर बल दृष्टिकोण का उपयोग कर सकते हैं:a<number>.pdfb<number>.pdf c<number>.pdf

a?.pdf a??.pdf b?.pdf b??.pdf c?.pdf c??.pdf

या इसे पतन {a,b,c}?{,?}.pdf


1
यह सबसे अच्छा जवाब है, क्योंकि यह की अधूरा उपयोग के किसी भी दावे से परे है है ls, stat, या कुछ और, और अनुरोध के अनुसार भी काम करता है।
काइल

5

यदि कोई अंतराल नहीं हैं , तो निम्नलिखित मददगार साबित हो सकता है (यद्यपि स्केच और धार-मामलों और व्यापकता के संबंध में मजबूत नहीं) - बस एक विचार प्राप्त करने के लिए:

FILES="c0.pdf"
for i in $(seq 1 20); do FILES="${FILES} c${i}.pdf"; done
gs [...args...] $FILES

यदि अंतराल हो सकता है, तो कुछ [ -f c${i}.pdf ]जांच जोड़ी जा सकती है।

संपादित करें इस उत्तर को भी देखें , जिसके अनुसार आप (बैश का उपयोग करके) कर सकते थे

gs [..args..] c{1..20}.pdf

जब तक आपके पास एक अच्छा कारण नहीं है, तब तक अपने शेल चर संदर्भ (जैसे, "$FILES"और "$i") को उद्धृत करना आम तौर पर एक अच्छा विचार है और आपको यकीन है कि आप जानते हैं कि आप क्या कर रहे हैं। (इसके विपरीत, जबकि ब्रेसिज़ महत्वपूर्ण हो सकते हैं, वे उद्धरण के रूप में महत्वपूर्ण नहीं हैं, इसलिए, उदाहरण के लिए, "c$i.pdf"काफी अच्छा है।) एक कमांड , जैसे कि जहां फ़ाइलों की एक अलग-अलग सूची होती है, एक अच्छे कारण की तरह लग सकता है। इसे उद्धृत किए बिना उपयोग करें (क्योंकि उस संदर्भ में काम नहीं करेगा)। … (Cont'd)gs  [ …args… ]  $FILES$FILES$FILES"$FILES"
जी-मैन का कहना है मोनिका '

(Cont'd)… लेकिन bash / POSIX गोले में एक चर को उद्धृत करने के लिए भूल जाने के सुरक्षा निहितार्थ देखें , विशेष रूप से, इसके लिए मेरा जवाब , नोटों के लिए बहु-शब्द चर को बश में सरणियों के रूप में कैसे संभालना है (जैसे, FILES=("c0.pdf")और FILES+=("c$i.pdf")); यह उत्तर भी , जो मेरे द्वारा सुझाई गई तकनीक का उपयोग करता है।
जी-मैन ने

1

बस थोर के जवाब को उद्धृत करना और ठीक करना ... कभी भी पार्स एलएस नहीं!

आप का उपयोग कर सकते हैं sort -V(एक गैर- POSIX एक्सटेंशन को सॉर्ट करने के लिए):

printf '%s\0' ./* | sort -zV \
    | xargs -0 gs -q -sPAPERSIZE=a4 -dNOPAUSE -dBATCH \
        -sDEVICE=pdfwrite -sOutputFile=out.pdf

(कुछ आदेशों के लिए, जाहिरा तौर पर जीएस के लिए एक ऐसी कमान है, आपको " " की बजाय " " की आवश्यकता है ... यदि कोई काम नहीं करता है, तो दूसरे को आज़माएं)


1
नहीं पार्स ls उत्पादन करना है, क्योंकि ls प्रदर्शित करता है फ़ाइल नाम न्यू लाइन द्वारा अलग किए गए एक फ़ाइल नाम में किसी भी रूप में मान्य के रूप में है, जबकि न्यू लाइन, लेकिन यहाँ आप के साथ एक ही बात कर रहे हैं statफ़ाइल नाम से शुरू होने के साथ समस्याओं की तरह (लेकिन कई अन्य मुद्दों को जोड़ने साथ -है, अगर वहाँ बहुत सारी फ़ाइलें हैं, समस्या statएक गैर पोर्टेबल आदेश किया जा रहा है)। और क्योंकि आपने IFS को समायोजित किए बिना या ग्लोब को अक्षम करने के बिना स्प्लिट + ग्लोब ऑपरेटर का उपयोग किया था, तब भी आपके पास स्पेस या टैब या वाइल्डकार्ड वर्णों के साथ फ़ाइल नाम के मुद्दे होंगे।
स्टीफन चेजलस

जीएनयू उपयोग करने के लिए sort -Vमज़बूती से, आप आवश्यकता होगी ${(z)"$(printf '%s\0' * | sort -zV)"}में zsh(हालांकि zshहै (n)संख्यात्मक प्रकार के लिए पहले से ही) या readarray -td '' files < <(printf '%s\0' * | sort -zV)में bash4.4+
स्टीफन चेज़लस

@ स्टीफनचैजेलस धन्यवाद, और आप सही हैं कि न्यूलाइन एक चिंता का विषय हो सकता है, लेकिन यह एकमात्र कारण नहीं है कि एलएस को पार्स न करें। और हाँ, मैं आलसी था और जोड़ नहीं था - या तो। लेकिन मुझे प्रिंटफ का इस्तेमाल करना चाहिए था ... मैं इसे बदल दूंगा।
पीटर

के लिए lsअकेले (कि -l के बिना है), वो क्या है अन्य चिंताओं ? ध्यान दें कि --नामक फ़ाइल के लिए मदद नहीं करेगा -
स्टीफन चेजलस

@ StéphaneChazelas संस्करणों के बीच अन्य अंतर हैं ... जैसे कुछ प्रिंट "कुल 0" पर, और नवीनतम एलएस संस्करण उन चीजों के आसपास उद्धरण भी चिपकाते हैं जहां आप उन्हें नहीं चाहते हैं ... touch \"test\"; ls -1उदाहरण के लिए '"test"'मेरे एलएस पर शो । यह बस पार्स होने का मतलब नहीं है ... यह एक यूजर इंटरफेस है, स्क्रिप्टिंग कमांड नहीं।
पीटर
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.