Argument list too longत्रुटि का सामना करते समय ध्यान रखने के लिए 3 प्रमुख बिंदु हैं :
कमांड-लाइन तर्कों की लंबाई ARG_MAXचर द्वारा सीमित है , जो कि POSIX परिभाषा द्वारा "... [m] पर्यावरणीय डेटा सहित निष्पादन कार्यों के लिए तर्क की अधिकतम लंबाई है " (जोर जोड़ा) "। अर्थात, जब शेल एक गैर निष्पादित करता है। -बिल्ट-इट कमांड, इसमें से एक exec()को उस कमांड की प्रक्रिया को स्पॉन करने के लिए कॉल करना होता है, और ARG_MAXयहीं से प्ले में आता है। इसके अलावा, कमांड का नाम या पथ (उदाहरण के लिए, /bin/echo) एक भूमिका निभाता है।
शेल में निर्मित कमांड शेल द्वारा निष्पादित किए जाते हैं, जिसका अर्थ है कि शेल exec()फ़ंक्शन के परिवार का उपयोग नहीं करता है और इसलिए ARG_MAXचर से प्रभावित नहीं होता है ।
जैसे कि कुछ आदेश, xargsऔर findके बारे में पता कर रहे हैं ARG_MAXचर और बार बार है कि सीमा के अंतर्गत कार्रवाई करने
उपरोक्त बिंदुओं से और जैसा कि कुसलानंद के संबंधित प्रश्न पर उत्कृष्ट उत्तर में दिखाया गया है , Argument list too longपर्यावरण के बड़े होने पर भी हो सकता है। इसलिए यह ध्यान में रखते हुए कि प्रत्येक उपयोगकर्ता का वातावरण भिन्न हो सकता है, और बाइट्स में तर्क का आकार प्रासंगिक है, एक ही संख्या में फाइलों / तर्कों के साथ आना मुश्किल है।
ऐसी त्रुटि को कैसे संभालें?
मुख्य बात यह है कि फ़ाइलों की संख्या पर ध्यान केंद्रित न करें, लेकिन इस बात पर ध्यान केंद्रित करें कि आप जिस कमांड का उपयोग करने जा रहे हैं, वह exec()फ़ंक्शन और स्पर्शरेखा के परिवार में है - स्टैक स्पेस।
शेल बिल्ट-इन का उपयोग करें
जैसा कि पहले चर्चा की गई है, शेल अंतर्निर्मित ARG_MAXसीमाएं प्रतिरक्षा हैं , जो कि forलूप, whileलूप, बिल्ट-इन echoऔर बिल्ट-इन जैसी चीजें हैं printf- वे सभी काफी अच्छा प्रदर्शन करेंगे।
for i in /path/to/dir/*; do cp "$i" /path/to/other/dir/; done
फ़ाइलों को हटाने के बारे में संबंधित प्रश्न पर , इस तरह एक समाधान था:
printf '%s\0' *.jpg | xargs -0 rm --
ध्यान दें कि यह शेल के अंतर्निर्मित का उपयोग करता है printf। यदि हम बाहरी कॉल कर रहे हैं printf, तो इसमें शामिल होंगे exec(), इसलिए बड़ी संख्या में तर्क विफल होंगे:
$ /usr/bin/printf "%s\0" {1..7000000}> /dev/null
bash: /usr/bin/printf: Argument list too long
बैश सरण
जॉलीग्रे के एक उत्तर के अनुसार , bashसरणियों पर सीमाएं नहीं लगाई जाती हैं, इसलिए फ़ाइल नाम के स्लाइस का उपयोग करना और लूप के पुनरावृत्ति प्रति स्लाइस का उपयोग किया जा सकता है, जैसा कि danjpreron के उत्तर में दिखाया गया है :
files=( /path/to/old_dir/*.prj )
for((I=0;I<${#files[*]};I+=1000)); do
cp -t /path/to/new_dir/ "${files[@]:I:1000}"
done
हालाँकि, इसे बैश-विशिष्ट और गैर-पॉसिक्स होने की सीमा है।
स्टैक स्पेस बढ़ाएं
कभी-कभी आप देख सकते हैं कि लोग स्टैक स्पेस को बढ़ाने का सुझाव देते हैं ulimit -s <NUM>; लिनक्स पर ARG_MAX मान प्रत्येक प्रोग्राम के लिए स्टैक स्पेस का 1 / 4th है, जिसका अर्थ है स्टैक स्पेस को आनुपातिक रूप से तर्क के लिए स्थान बढ़ाना।
# getconf reports value in bytes, ulimit -s in kilobytes
$ getconf ARG_MAX
2097152
$ echo $(( $(getconf ARG_MAX)*4 ))
8388608
$ printf "%dK\n" $(ulimit -s) | numfmt --from=iec --to=none
8388608
# Increasing stack space results in increated ARG_MAX value
$ ulimit -s 16384
$ getconf ARG_MAX
4194304
लिनक्स जर्नल का हवाला देते हुए फ्रेंक डेर्नोनकोर्ट के जवाब के अनुसार , कोई भी तर्क के लिए अधिकतम मेमोरी पेजों के लिए बड़े मूल्य के साथ लिनक्स कर्नेल को फिर से जोड़ सकता है, हालांकि, यह आवश्यकता से अधिक काम है और cc लिनक्स जर्नल लेख में बताए गए कारनामों के लिए संभावित खोलता है।
शेल से बचें
एक और तरीका है, का उपयोग करना है pythonया python3जो डिफ़ॉल्ट रूप से उबंटू के साथ आता है। अजगर + यहाँ-डॉक्टर का उदाहरण नीचे दिया गया है, मैं व्यक्तिगत रूप से फ़ाइलों की एक बड़ी निर्देशिका की प्रतिलिपि बनाने के लिए 40,000 वस्तुओं की रेंज में कहीं इस्तेमाल किया गया है:
$ python <<EOF
> import shutil
> import os
> for f in os.listdir('.'):
> if os.path.isfile(f):
> shutil.copy(f,'./newdir/')
> EOF
पुनरावर्ती ट्रैवर्सल्स के लिए, आप os.walk का उपयोग कर सकते हैं ।
यह भी देखें: