Argument list too long
ত্রুটির মুখোমুখি হওয়ার সময় মনে রাখা 3 টি মূল বিষয় রয়েছে :
কমান্ড-লাইন আর্গুমেন্টগুলির দৈর্ঘ্য ARG_MAX
পরিবর্তনশীল দ্বারা সীমাবদ্ধ , যা পসিক্স সংজ্ঞা দ্বারা "... [মি।] পরিবেশের ডেটা সহ এক্সিকিউটিভ ফাংশনগুলিতে আর্গুমেন্টের সর্বোচ্চ দৈর্ঘ্য " (জোর যুক্ত) "। এটি, যখন শেল একটি অজানা কার্যকর করে -bilt-it কমান্ড, 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
অ্যারেগুলিতে সীমাবদ্ধতা আরোপ করে না, সুতরাং ডানজপ্রাইনের উত্তরে দেখানো হিসাবে ফাইলের অ্যারে তৈরি করা এবং লুপের পুনরাবৃত্তির জন্য প্রতি টুকরোগুলি ব্যবহার করা যেতে পারে :
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>
; লিনাক্স এআরজি_ম্যাক্সের মান প্রতিটি প্রোগ্রামের জন্য স্ট্যাক স্পেসের 1/4 র্থ হয়, যার মানে স্ট্যাক স্পেস বাড়িয়ে আনুপাতিকভাবে আর্গুমেন্টের জন্য স্থান বৃদ্ধি করে।
# 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
লিনাক্স জার্নালকে উদ্ধৃত করে ফ্র্যাঙ্ক ডারননকোর্টের উত্তর অনুসারে , যুক্তিগুলির জন্য সর্বাধিক মেমরি পৃষ্ঠাগুলির জন্য লিনাক্স কার্নেলটি আরও বড় আকারের সাথে পুনর্নির্মাণ করতে পারে, তবে এটি প্রয়োজনের চেয়ে বেশি কাজ এবং উদ্ধৃত লিনাক্স জার্নাল নিবন্ধে বর্ণিত শোষণের সম্ভাবনা উন্মুক্ত করে।
শেল এড়িয়ে চলুন
অন্য উপায়, ব্যবহার 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 ব্যবহার করতে পারেন ।
আরো দেখুন: