ফাইলগুলি অনুলিপি করার সময় যুক্তি তালিকা খুব দীর্ঘ too


26

আমি কেবলমাত্র কীভাবে নির্দিষ্ট এক্সটেনশনের ফাইলগুলি গণনা করতে পারি সে সম্পর্কিত একটি প্রশ্ন জিজ্ঞাসা করেছি। এখন আমি cpএই ফাইলগুলিকে নতুন করতে চাই dir

আমি চেষ্টা করছি,

cp *.prj ../prjshp/

এবং

cp * | grep '\.prj$' ../prjshp/

তবে তারা একই ত্রুটি দিচ্ছে,

বাশ: / বিন / সিপি: যুক্তি তালিকা খুব দীর্ঘ

আমি কীভাবে এগুলি অনুলিপি করব?


উত্তর:


36

cp *.prj ../prjshp/সঠিক কমান্ড, তবে আপনি একটি বিরল ক্ষেত্রে আঘাত করেছেন যেখানে এটি একটি আকার সীমাতে চলে। আপনি যে দ্বিতীয় কমান্ডটি চেষ্টা করেছেন তা কোনও অর্থবোধ করে না।

একটি পদ্ধতি হ'ল cpখণ্ডে ফাইল চালানো । findকমান্ড জানে এই কিভাবে করতে হবে:

find -maxdepth 1 -name '*.prj' -exec mv -t ../prjshp {} +
  • find বর্তমান ডিরেক্টরি এবং এর নীচের ডিরেক্টরিগুলি পুনরাবৃত্তভাবে অনুসরণ করে।
  • -maxdepth 1 এর অর্থ 1 এর গভীরতায় থামানো, অর্থাৎ উপ-ডিরেক্টরিতে পুনরাবৃত্তি করবেন না।
  • -name '*.prj'যার অর্থ কেবল সেই ফাইলগুলিতে কাজ করা যার নাম নির্দিষ্ট প্যাটার্নের সাথে মেলে। প্যাটার্নের চারপাশে উদ্ধৃতিগুলি নোট করুন: এটি findশেল দ্বারা নয়, আদেশ দ্বারা ব্যাখ্যা করা হবে ।
  • -exec … {} +এর অর্থ সমস্ত ফাইলের জন্য নির্দিষ্ট কমান্ড কার্যকর করা। কমান্ড লাইন সীমা অতিক্রম না করার যত্ন নিয়ে এটি প্রয়োজনে একাধিকবার কমান্ডের আবেদন করে।
  • mv -t ../prjshpনির্দিষ্ট ফাইলগুলিকে এতে সরানো হয় ../prjshp-tবিকল্প একটি সীমাবদ্ধতা কারণে এখানে ব্যবহার করা হয় findকমান্ড প্রয়োগ করুন: পাওয়া ফাইল (দ্বারা প্রতীক {}) কমান্ডের গত আর্গুমেন্ট হিসাবে পাস করা হয়, আপনি এটি পরে গন্তব্য জুড়তে পারবেন না।

আর একটি পদ্ধতি ব্যবহার করা হয় rsync

rsync -r --include='*.prj' --exclude='*' . ../prjshp
  • rsync -r … . ../prjshpবর্তমান ডিরেক্টরিটি ../prjshpপুনরাবৃত্তিতে অনুলিপি করে ।
  • --include='*.prj' --exclude='*'মানে ফাইলের সাথে মিলে থাকা অনুলিপি করা *.prjএবং সমস্ত কিছু বাদ দেওয়া (উপ-ডিরেক্টরিগুলি সহ, সুতরাং .prjসাব-ডিরেক্টরিতে ফাইলগুলি পাওয়া যাবে না)।

3
rsync, এখানকার সবচেয়ে সহজ সমাধান।
ntk4

কিছুটা নিটপিকি হতে, দ্বিতীয় কমান্ডটি cp * | grep '\.prj$' ../prjshp/ কোনও অর্থবোধ করে না, তবে সিন্ট্যাক্টিক্যালি বৈধ হতে পারে, যদি *সর্বশেষ ফাইলটির তালিকাতে ডিরেক্টরি হয় (ডিরেক্টরি cp SOURCE1 SOURCE2....DEST) aka পাইপটি কোনও ধারণা দেয় না, নিশ্চিত করে, তবে শেল সম্পর্কিত হিসাবে সিন্থেটিকভাবে বৈধ থাকে - এটি dup()ফাইলের বর্ণনাকারীদের ঠিক ঠিক করবে, পাইপের পাঠক প্রান্তটি কোনও তথ্য পাবে না কারণ cpকোনও কিছু লিখেনি ।
সের্গেই কোলোডিয়াজনি

অনুসন্ধান এবং আরএসসিএনসি উভয়ই একই যুক্তি তালিকার জন্য আমার পক্ষে দীর্ঘতর ত্রুটি তৈরি করেছিল। লুপটি ছিল সহজতম কাজ।
মিজান-উদ-দিন

আরএসসিএনসি হ'ল যে কোনও গণ অনুলিপি করার উপায়, যদিও আমি লিনাক্সের সাথে কতটা দূরে এসেছি এবং আমরা এর মতো নির্বোধ ত্রুটি / বাগ পেয়েছি এবং হ্যাঁ আমি এটিকে একটি ত্রুটি / বাগ হিসাবে বিবেচনা করব।
মিচেলকে

22

এই কমান্ডটি ফাইলগুলি একে একে অনুলিপি করে এবং *একক cpকমান্ডে প্রসারিত করার জন্য যদি এর মধ্যে অনেক বেশি থাকে তবেও এটি কাজ করবে :

for i in *; do cp "$i" ../prjshp/; done

এটি আমার পক্ষে কাজ করে।
1rq3fea324 রবিবার

1
সহজ এবং কার্যকর। একটি প্রকল্পের জন্য আমি একটি ভিডিও থেকে বেরিয়েছি ~ 1/4 মিলিয়ন jpegs সরানোর ক্ষেত্রে আমার একই সমস্যা ছিল। এটিই আমি ব্যবহার করি approach
বয়স্ক

5

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 ব্যবহার করতে পারেন ।

আরো দেখুন:


2

এই প্রোগ্রামটিতে, ফাইল এর hordes সঙ্গে তার আচরণ জন্য অনুকূল সরঞ্জাম findএবং xargs। দেখুন man find। দেখুন man xargsfind, তার -print0স্যুইচ সহ, NULফাইল-নামগুলির একটি পৃথক তালিকা তৈরি করে (ফাইলের নামগুলিতে কোনও অক্ষর নির্বাহক থাকতে পারে NULবা /) যা xargsবোঝে, -0সুইচটি ব্যবহার করে । xargsতারপরে অনুমোদিততম দীর্ঘতম কমান্ডটি তৈরি করে (সর্বাধিক ফাইল-নাম, শেষে অর্ধ-ফাইল নাম নেই) এবং এটি কার্যকর করে। xargsআর findকোনও ফাইলের নাম সরবরাহ না করা পর্যন্ত এটি পুনরাবৃত্তি করে । চালান xargs --show-limits </dev/nullসীমা দেখতে।

আপনার সমস্যা সমাধানের জন্য, (এবং man cpএটি অনুসন্ধানের পরে --target-directory=):

find . -maxdepth 1 -type f -name '*.prj' -print0 | xargs -0 cp --target-directory=../prjshp/
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.