एलएस के लिए तर्क सूची बहुत लंबी है


48

मुझे ls *.txt | wc -lनिर्देशिका में कोशिश करते समय निम्नलिखित त्रुटि मिलती है जिसमें कई फाइलें हैं:

-bash: /bin/ls: Argument list too long

क्या इस "तर्क सूची" की सीमा डिस्ट्रो या कंप्यूटर की कल्पना पर निर्भर करती है? आमतौर पर, मैं इस तरह के बड़े परिणाम का परिणाम कुछ अन्य कमांड ( wc -lउदाहरण के लिए) पर रखूंगा, इसलिए मुझे टर्मिनल की सीमाओं से कोई सरोकार नहीं है।



@ मैनटवर्क हाँ, मैंने उन सवालों को देखा। बस एक सामान्य तरीके से एक लंबे आउटपुट को उपयोग करने या पुनर्निर्देशित करने का एक बेहतर तरीका सोच रहा था।

आप अधिकांश यूनिक्स आधारित प्रणालियों पर सीमा प्राप्त करने के लिए getconf ARG_MAX का उपयोग कर सकते हैं
प्रशांत

जवाबों:


49

आपकी त्रुटि संदेश तर्क सूची बहुत लंबी * की * से आती है ls *.txt

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

पाइप के आकार पर ऐसी कोई सीमा नहीं है। तो आप बस इस आदेश को जारी कर सकते हैं:

find -type f -name '*.txt'  | wc -l

एनबी: आधुनिक लिनक्स पर, फ़ाइल नाम (जैसे नईलाइन्स) में अजीब अक्षर lsया जैसे टूल के साथ बच जाएंगे find, लेकिन फिर भी * से प्रदर्शित होते हैं । यदि आप एक पुराने यूनिक्स पर हैं, तो आपको इस कमांड की आवश्यकता होगी

find -type f -name '*.txt' -exec echo \;  | wc -l

NB2: मैं सोच रहा था कि कोई अपने नाम से एक नई लाइन के साथ फाइल कैसे बना सकता है। यह मुश्किल नहीं है, एक बार जब आप चाल जानते हैं:

touch "hello
world"

1
मैंने उस मामले में काम करने के लिए इसे थोड़ा संशोधित किया जब उनमें नई कहानियों के साथ फ़ाइलनाम होते हैं। -maxdepth 1यदि आप उपनिर्देशिकाओं में फ़ाइलों की गणना करने का इरादा नहीं कर रहे हैं तो आप भी जोड़ना चाह सकते हैं।
शॉन जे। गोफ

आप की जरूरत नहीं है -exec echo \;
मिकेल

@ ShawnJ.Goff मैंने इसका परीक्षण किया है। लगता है जीएनयू के वर्तमान संस्करण में `echo` की कोई ज़रूरत नहीं है
कोरेन

@Coren @Mikel - हर किसी के पास GNU नहीं है findfindओएस पर एक्स और बिजीबॉक्स आधारित सिस्टम पर, और मैं किसी भी बीएसडी आधारित प्रणाली लगता होगा गिनती के साथ उस में एक नई पंक्ति है, जो गंदगी होगा साथ फ़ाइल नाम को दर्शाता है।
शॉन जे। गोफ

है ना? wc -lगिनती नई है। इसलिए हम चाहते हैं कि यह नई हो।
मिकेल

11

यह मुख्य रूप से लिनक्स कर्नेल के आपके संस्करण पर निर्भर करता है।

आपको चलाकर अपने सिस्टम की सीमा देखने में सक्षम होना चाहिए

getconf ARG_MAX

जो आपको बताता है कि शेल द्वारा विस्तारित किए जाने के बाद एक कमांड लाइन की अधिकतम संख्या बाइट्स हो सकती है।

लिनक्स <2.6.23 में, सीमा आमतौर पर 128 KB है।

लिनक्स में = = 2.6.25, सीमा या तो 128 KB है, या आपके स्टैक आकार (देखें ulimit -s) का 1/4 , जो भी बड़ा है।

सभी विवरणों के लिए निष्पादित (2) मैन पेज देखें।


दुर्भाग्य से, पाइपिंग ls *.txtसमस्या को ठीक करने वाली नहीं है, क्योंकि सीमा ऑपरेटिंग सिस्टम में है, शेल नहीं।

शेल का विस्तार होता है *.txt, फिर कॉल करने का प्रयास करता है

exec("ls", "a.txt", "b.txt", ...)

और आपके पास इतनी सारी फाइलें मेल खाती हैं *.txtकि आप 128 KB की सीमा से अधिक हो जाते हैं।

आपको कुछ ऐसा करना होगा

find . -maxdepth 1 -name "*.txt" | wc -l

बजाय।

(और शॉल जे। गोफ की टिप्पणियों को उन नामों के बारे में नीचे देखिए जिनमें नए नाम हैं।)


एक उत्तर को अप् ट करने में असमर्थ होने के लिए क्षमा करें। अधिक प्रतिष्ठा चाहिए। :( आप सभी को धन्यवाद !!

क्या आप बता सकते हैं कि अंतिम पंक्ति में क्या .और क्या है -maxdepth 1? धन्यवाद! : डी
गुइलहर्मे सालोमे

2
@ GuilhermeSalomé का .अर्थ है वर्तमान निर्देशिका, -maxdepth 1इसका मतलब है कि यह उपनिर्देशिकाओं में नहीं दिखता है। इसका उद्देश्य उसी फाइलों का मिलान करना था *.txt
मिकेल

9

एक और समाधान:

ls | grep -c '\.txt$'

भले ही lsउत्पादन से अधिक उत्पादन ls *.txt(या उत्पादन करने का प्रयास) करता है, यह "तर्क बहुत लंबा" समस्या में नहीं चलता है, क्योंकि आप किसी भी तर्क को पारित नहीं कर रहे हैं ls। ध्यान दें कि grepफ़ाइल मिलान पैटर्न के बजाय एक नियमित अभिव्यक्ति लेता है।

आप उपयोग करना चाहते हैं:

ls -U | grep -c '\.txt$'

( lsइस विकल्प का समर्थन करने के अपने संस्करण को मानते हुए )। यह lsअपने आउटपुट को क्रमबद्ध नहीं करने के लिए कहता है , जो समय और मेमोरी दोनों को बचा सकता है - और इस मामले में आदेश कोई फर्क नहीं पड़ता, क्योंकि आप सिर्फ फाइलों की गिनती कर रहे हैं। आउटपुट को सॉर्ट करने में खर्च किए गए संसाधन आमतौर पर महत्वपूर्ण नहीं होते हैं, लेकिन इस मामले में हम पहले से ही जानते हैं कि आपके पास बहुत बड़ी संख्या में *.txtफाइलें हैं।

और आपको अपनी फ़ाइलों को पुनर्गठित करने पर विचार करना चाहिए ताकि आपके पास एक ही निर्देशिका में इतने सारे न हों। यह संभव नहीं है या संभव नहीं है।


1

MAX_ARG_PAGES कर्नेल पैरामीटर प्रतीत होता है। का उपयोग करना findऔर xargsइस सीमा को संबोधित करने के लिए एक विशिष्ट संयोजन है, लेकिन मुझे यकीन नहीं है कि यह काम करेगा wc

find . -name \*\.txtकिसी फ़ाइल के आउटपुट को पाइप करना और उस फ़ाइल में लाइनों को गिनना एक वर्कअराउंड के रूप में काम करना चाहिए।


आप lsआउटपुट के साथ कुछ भी कर सकते हैं , इससे हल नहीं होगा। जब तक * .txt वाइल्डकार्ड सीमा से अधिक विस्तारित है, तब तक lsकिसी भी आउटपुट को शुरू करने और उत्पन्न करने से पहले विफल हो जाएगा ।
मैनेटवर्क

सच है, मैंने अपना जवाब अपडेट कर दिया है।
ब्राम

बेहतर। लेकिन इसे बदलने के लिए lsआपको -maxdepth 1उप-सीमाओं को पुन: स्कैन करने से बचने के लिए निर्दिष्ट करना चाहिए ।
मैनेटवर्क

एक उत्तर को अप् ट करने में असमर्थ होने के लिए क्षमा करें। अधिक प्रतिष्ठा चाहिए। :(

0

यह गंदा हो सकता है लेकिन यह मेरी जरूरतों के लिए और मेरी योग्यता के भीतर काम करता है। मुझे नहीं लगता कि यह बहुत तेज़ी से प्रदर्शन करता है, लेकिन इसने मुझे अपने दिन के साथ आने की अनुमति दी।

ls | grep jpg | <something>

मैं jpgs की 90,000 लंबी सूची प्राप्त कर रहा था और टाइमलैप्स बनाने के लिए उन्हें एवनक को पाइप कर रहा था।

मैं पहले ls * .jpg का उपयोग कर रहा था इससे पहले कि मैं इस मुद्दे पर भागता हूँ।

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