বাশ জন্য বনাম অনুসন্ধান


28

ফাইলগুলি লুপ করার সময় দুটি উপায় থাকে:

  1. একটি forলুপ ব্যবহার করুন :

    for f in *; do
        echo "$f"
    done
  2. ব্যবহার find:

    find * -prune | while read f; do 
        echo "$f"
    done

এই দুটি লুপ ধরে নিলে ফাইলগুলির একই তালিকা পাওয়া যাবে, পারফোমেন্স এবং হ্যান্ডলিংয়ে এই দুটি বিকল্পের মধ্যে পার্থক্য কী ?


1
কেন? findএটি খুঁজে পাওয়া ফাইলগুলি খুলবে না। এখানে বিপুল সংখ্যক ফাইলের প্রতি সম্মান সহকারে আমি আপনাকে কেবল কামড়ানো দেখতে পাচ্ছি তা হ'ল ARG_MAX
কোজিরো

1
উত্তর এবং মন্তব্যগুলি দেখুন যা আপনাকে জানায় যে read fফাইলগুলি পড়ার সাথে সাথে নামগুলি ছড়িয়ে দেবে (যেমন নেতৃস্থানীয় ফাঁকা নাম সহ)। এছাড়াও find * -pruneএকটি খুব সংবর্ত পথ কেবল বলতে হবে বলে মনে হয় ls -1তাই না?
ইয়ান ডি অ্যালেন

4
ধরে নিবেন না যে দুটি লুপ একই ফাইলের সেট খুঁজে পাবে; বেশিরভাগ ক্ষেত্রে, তারা তা করবে না। এছাড়াও, এটি হওয়া উচিত find ., না find *
অ্যালেক্সিস

1
@ ইটারডন হ্যাঁ, পার্সিং ls -lকরা একটি খারাপ ধারণা। তবে পার্সিং ls -1(এটি একটি আন 1নয় l) পার্সিংয়ের চেয়ে খারাপ নয় find * -prune। দু'জনেই নামের সাথে নতুন লাইনের ফাইলগুলিতে ব্যর্থ।
ইয়ান ডি অ্যালেন

5
আমি সন্দেহ করি যে আমরা প্রত্যেকে এই প্রশ্ন এবং প্রতিক্রিয়াগুলিতে প্রশ্নের মধ্যে থাকা স্ক্রিপ্টের জীবনের তুলনায় পারফরম্যান্সের মোট পার্থক্যের চেয়ে বেশি সময় ব্যয় করেছি।
এমপিজ 0

উত্তর:


9

1।

প্রথমটি:

for f in *; do
  echo "$f"
done

নামক ফাইলের জন্য ব্যর্থ হয় -n, -eমত রূপ-nene এবং কিছু ব্যাশ স্থাপনার সঙ্গে, ফাইলের নাম ব্যাকস্ল্যাশ সম্বলিত।

দ্বিতীয়:

find * -prune | while read f; do 
  echo "$f"
done

এমনকি আরো মামলা ব্যর্থ (ফাইল নামক !, -H, -name,( , ফাইল নাম যে শুরু করলে বা ঐ খালি সঙ্গে শেষ বা সম্পর্কে newline অক্ষর ...)

এটি শেলটি প্রসারিত হয় *, findআর্গুমেন্ট হিসাবে প্রাপ্ত ফাইলগুলি মুদ্রণ করা ছাড়া কিছুই করে না। আপনি পাশাপাশি printf '%s\n'পরিবর্তে ব্যবহার করতে পারেন যা printfবিল্টিন হিসাবে রয়েছে অনেকগুলি আরোগ্যও এড়াতে পারে সম্ভাব্য ।

2।

এর সম্প্রসারণ *বাছাই করা হয়, যদি আপনার বাছাইয়ের প্রয়োজন না হয় তবে আপনি এটি কিছুটা দ্রুত তৈরি করতে পারেন। ইন zsh:

for f (*(oN)) printf '%s\n' $f

বা সহজভাবে:

printf '%s\n' *(oN)

bash যতদূর আমি বলতে পারি তার সমতুল্য নেই, তাই আপনাকে অবলম্বন করতে হবে find

3।

find . ! -name . -prune ! -name '.*' -print0 |
  while IFS= read -rd '' f; do
    printf '%s\n' "$f"
  done

(উপরে একটি জিএনইউ / বিএসডি -print0অ-মানক এক্সটেনশন ব্যবহার করে)।

এটি এখনও একটি ফাইন্ড কমান্ড তৈরি এবং একটি ধীর while readলুপ ব্যবহার জড়িত , সুতরাং এটি forফাইলের তালিকা বিশাল না হওয়া পর্যন্ত লুপটি ব্যবহারের চেয়ে সম্ভবত ধীর হবে ।

4।

এছাড়াও, শেল ওয়াইল্ডকার্ড সম্প্রসারণের বিপরীতে, প্রতিটি ফাইলে findএকটি lstatসিস্টেম কল করবে , সুতরাং নোট-বাছাই করা তার পক্ষে ক্ষতিপূরণ পাবে এমন সম্ভাবনা কম।

জিএনইউ / বিএসডি-র findসাহায্যে, তাদের -maxdepthএক্সটেনশন ব্যবহার করে এড়ানো যায় যা এটি সংরক্ষণ করে একটি অপ্টিমাইজেশন ট্রিগার করবে lstat:

find . -maxdepth 1 ! -name '.*' -print0 |
  while IFS= read -rd '' f; do
    printf '%s\n' "$f"
  done

কারণ findফাইলের নামগুলি খুঁজে পাওয়ার সাথে সাথে আউটপুট করা শুরু করে (স্টডিও আউটপুট বাফারিং ব্যতীত) যেখানে লুপটিতে আপনি যা করেন তা সময়সাপেক্ষ হয় এবং ফাইলের নামের তালিকাটি স্টডিও বাফারের চেয়ে বেশি হলে (4) / 8 কেবি)। সেক্ষেত্রে findসমস্ত ফাইল সন্ধান শেষ করার আগে লুপের মধ্যে প্রক্রিয়াজাতকরণ শুরু হবে । জিএনইউ এবং ফ্রিবিএসডি সিস্টেমগুলিতে, আপনি stdbufতাড়াতাড়ি হওয়ার কারণ হিসাবে ব্যবহার করতে পারেন (স্টিডিও বাফারিং অক্ষম করা)।

5।

এর সাথে প্রতিটি ফাইলের কমান্ড চালানোর জন্য পসিক্স / স্ট্যান্ডার্ড / পোর্টেবল উপায় findহ'ল -execপ্রিডিকেট ব্যবহার করা :

find . ! -name . -prune ! -name '.*' -exec some-cmd {} ';'

echoযদিও এর ক্ষেত্রে এটি শেলের লুপিংয়ের চেয়ে কম দক্ষ কারণ শেলের একটি বিল্টিন সংস্করণ থাকবে echoযখন findএকটি নতুন প্রক্রিয়া তৈরি করতে /bin/echoহবে এবং প্রতিটি ফাইলের জন্য এটি সম্পাদন করতে হবে।

আপনার যদি কয়েকটি কমান্ড চালানোর প্রয়োজন হয় তবে আপনি এটি করতে পারেন:

find . ! -name . -prune ! -name '.*' -exec cmd1 {} ';' -exec cmd2 {} ';'

তবে সাবধান থাকুন যে cmd2শুধুমাত্র cmd1সফল হলে মৃত্যুদন্ড কার্যকর করা হয়।

6।

প্রতিটি ফাইলের জন্য জটিল কমান্ডগুলি চালনার এক সাধারণ উপায় হ'ল এর সাথে শেল কল করা -exec ... {} +:

find . ! -name . -prune ! -name '.*' -exec sh -c '
  for f do
    cmd1 "$f"
    cmd2 "$f"
  done' sh {} +

এই সময়টি echoথেকে আমরা দক্ষ হয়ে ফিরে এসেছি যেহেতু আমরা shএকটি বিল্টিন ব্যবহার করছি এবং -exec +সংস্করণটি যত কম shসম্ভব স্প্যান হয়েছে ।

7।

ইন 200,000 ফাইলগুলির সাথে একটি ডিরেক্টরি আমার পরীক্ষার ext4 এই সংক্ষিপ্ত নামের সাথে, zshএক (অনুচ্ছেদ 2.), এ পর্যন্ত দ্রুততম দ্বারা প্রথম সহজ দ্বারা অনুসরণ for i in *লুপ (যদিও স্বাভাবিক হিসাবে, bashঅনেক যে জন্য অন্যান্য শাঁস তুলনায় ধীর যায়)।


কী !find কমান্ডের না?
rubo77

@ রুবো 77।, অবহেলার !জন্য। ! -name . -prune more...কি করতে হবে -prune(এবং more...যেহেতু -pruneসবসময় সত্য ফেরৎ) প্রত্যেক ফাইল কিন্তু .। সুতরাং এটি more...সমস্ত ফাইলগুলিতে .করবে, তবে বাদ দেবে .এবং এর সাব-ডিরেক্টরিতে নেমে আসবে না .। সুতরাং এটি GNU এর মান সমতুল্য -mindepth 1 -maxdepth 1
স্টাফেন চেজেলাস

18

আমি এটি 2259 এন্ট্রি সহ একটি ডিরেক্টরিতে চেষ্টা করেছি এবং timeকমান্ডটি ব্যবহার করেছি ।

time for f in *; do echo "$f"; done(ফাইলগুলি বিয়োগ করে!) এর আউটপুট হল:

real    0m0.062s
user    0m0.036s
sys     0m0.012s

time find * -prune | while read f; do echo "$f"; done(ফাইলগুলি বিয়োগ করে!) এর আউটপুট হল:

real    0m0.131s
user    0m0.056s
sys     0m0.060s

আমি প্রতিটি কমান্ড বেশ কয়েকবার চালিয়েছি, যাতে ক্যাশে মিস করা যায় না। এটি প্রস্তাব দেয় যে এটি রাখার bashজন্য (আমি ভিতরে ...) findআউটপুট ব্যবহার করার এবং পাইপিংয়ের চেয়ে দ্রুত (এতে bash)

কেবল সম্পূর্ণতার জন্য, আমি পাইপটি বাদ দিয়েছিলাম find, যেহেতু আপনার উদাহরণস্বরূপ এটি সম্পূর্ণ অপ্রয়োজনীয়। ন্যায়বিচারের ফলাফল find * -prune:

real    0m0.053s
user    0m0.016s
sys     0m0.024s

এছাড়াও, time echo *(আউটপুট নতুন লাইন পৃথক নয়, হায়):

real    0m0.009s
user    0m0.008s
sys     0m0.000s

এই মুহুর্তে, আমি সন্দেহ করি কারণটি echo *দ্রুততর কারণ এটি এতগুলি নতুন লাইন আউটপুট দিচ্ছে না, ফলে আউটপুটটি এত বেশি স্ক্রোল হচ্ছে না। আসুন পরীক্ষা করি ...

time find * -prune | while read f; do echo "$f"; done > /dev/null

উৎপাদনের:

real    0m0.109s
user    0m0.076s
sys     0m0.032s

time find * -prune > /dev/nullফলনের সময় :

real    0m0.027s
user    0m0.008s
sys     0m0.012s

এবং time for f in *; do echo "$f"; done > /dev/nullফলন:

real    0m0.040s
user    0m0.036s
sys     0m0.004s

এবং অবশেষে: time echo * > /dev/nullফলন:

real    0m0.011s
user    0m0.012s
sys     0m0.000s

কিছু কিছু প্রকারভেদ এলোমেলো কারণগুলির দ্বারা গণ্য করা যেতে পারে তবে এটি স্পষ্ট বলে মনে হয়:

  • আউটপুট ধীর
  • পাইপিংয়ের জন্য কিছুটা ব্যয় হয়
  • for f in *; do ...নিজের থেকে ধীর find * -prune, তবে পাইপ জড়িত উপরের নির্মাণগুলির জন্য দ্রুততর।

এছাড়াও, একদিকে যেমন উভয় পন্থাগুলি খালি জায়গাগুলির সাথে নামগুলি পরিচালনা করতে উপস্থিত হয়।

সম্পাদনা করুন:

সময়টা find . -maxdepth 1 > /dev/nullবনাম find * -prune > /dev/null:

time find . -maxdepth 1 > /dev/null:

real    0m0.018s
user    0m0.008s
sys     0m0.008s

find * -prune > /dev/null:

real    0m0.031s
user    0m0.020s
sys     0m0.008s

সুতরাং, অতিরিক্ত উপসংহার:

  • find * -pruneআগের চেয়ে ধীর find . -maxdepth 1- শেলটি একটি গ্লোব প্রক্রিয়াজাত করছে, তারপরে একটি (বৃহত্তর) কমান্ড লাইন তৈরি করছে find। নোট: find . -pruneঠিক ফিরে .

আরও পরীক্ষা time find . -maxdepth 1 -exec echo {} \; >/dev/null:

real    0m3.389s
user    0m0.040s
sys     0m0.412s

উপসংহার:

  • এখন পর্যন্ত এটি করার ধীরতম উপায় way এই দৃষ্টিভঙ্গির প্রস্তাব দেওয়া হয়েছিল এমন উত্তরের মন্তব্যে যেমন উল্লেখ করা হয়েছিল, প্রতিটি যুক্তি একটি শেল তৈরি করে।

কোন পাইপ অপ্রয়োজনীয়? আপনি পাইপ ছাড়া লাইনটি ব্যবহার করতে পারেন?
rubo77

2
@ রুবো find * -prune | while read f; do echo "$f"; donethe। এর অপ্রয়োজনীয় পাইপ রয়েছে - সমস্ত পাইপ যা করছে তা হ'ল findআউটপুটগুলি হ'ল তার নিজস্ব। পাইপ ব্যতীত এটি find * -prune কেবল সরল হবে পাইপটি কেবলমাত্র বিশেষভাবে অপ্রয়োজনীয় কারণ পাইপের অন্য প্রান্তের জিনিসটি স্ট্যান্ডিনকে কেবল স্ট্যান্ডআউট অনুলিপি করে (বেশিরভাগ অংশে)। এটি একটি ব্যয়বহুল কোন বিকল্প নেই। আপনি যদি সন্ধানের আউটপুট দিয়ে স্টাফ করতে চান তবে এটিকে আবার ফিরিয়ে আনা ব্যতীত অন্যরকম।
ফিল

হতে পারে মূল টাইমকনসমিংটি হ'ল *। হিসাবে BitsOfNix বলেন: আমি এখনও দৃঢ়ভাবে ব্যবহার করবেন সুপারিশ *এবং .জন্য findপরিবর্তে।
rubo77

@ রুবো 77 এইভাবে মনে হচ্ছে। আমার ধারণা আমি সেটিকে উপেক্ষা করেছি। আমি আমার সিস্টেমের জন্য অনুসন্ধানগুলি যুক্ত করেছি। আমি ধরে নিয়েছি find . -pruneদ্রুততর কারণ findএকটি ডিরেক্টরি এন্ট্রি ভারব্যাটিম পড়বে, যখন শেলটি একইভাবে করবে, সম্ভাব্যভাবে গ্লোবটির সাথে মিলবে (এর জন্য অনুকূলিত হতে পারে *), তারপরে বড় কমান্ড লাইন তৈরি করবে find
ফিল

1
find . -pruneশুধুমাত্র .আমার সিস্টেমে মুদ্রণ । এটি মোটেও কোনও কাজ করে না। এটি find * -pruneবর্তমান ডিরেক্টরিতে সমস্ত নাম দেখায় তেমন এক নয় । একটি খালি read fউইন্ডো নেতৃস্থানীয় স্পেস সহ ফাইলের নাম লিখবে।
ইয়ান ডি অ্যালেন

10

আমি অবশ্যই অনুসন্ধানের সাথে যাব যদিও আমি আপনার অনুসন্ধানকে কেবল এটিতে পরিবর্তন করব:

find . -maxdepth 1 -exec echo {} \;

পারফরম্যান্স ওয়াইস, findআপনার অবশ্যই প্রয়োজনের উপর নির্ভর করে অনেক দ্রুত। বর্তমানে forএটির সাথে আপনার যা রয়েছে তা কেবলমাত্র বর্তমান ডিরেক্টরিতে ফাইল / ডিরেক্টরিগুলি প্রদর্শন করবে তবে ডিরেক্টরিগুলির সামগ্রী নয়। আপনি যদি এটি ব্যবহার করেন তবে এটি উপ ডিরেক্টরিগুলির সামগ্রীগুলিও প্রদর্শন করবে show

আমি বলতে খোঁজ সঙ্গে যেহেতু উত্তম আপনার প্রথম প্রসারিত করা করতে হবে এবং আমি ভীত যে আপনি যদি ফাইল বিপুল পরিমাণ সঙ্গে একটি ডিরেক্টরির আছে এটা ত্রুটি দিতে পারে আছি আর্গুমেন্ট তালিকার অত্যন্ত দীর্ঘ । একই জন্য যায়for*find *

উদাহরণস্বরূপ, আমি বর্তমানে যে সিস্টেমে ব্যবহার করি সেগুলির একটিতে 2 মিলিয়ন ফাইলের (<100k প্রতিটি) সহ কয়েকটি ডিরেক্টরি রয়েছে:

find *
-bash: /usr/bin/find: Argument list too long

আমি -pruneদুটি উদাহরণকে আরও এক করে করার জন্য যুক্ত করেছি । এবং আমি পাইপটি এমন সময় পছন্দ করি যাতে
লুপটিতে


হার্ড সীমা পরিবর্তন করা আমার পিওভির পক্ষে কমই যথাযথ কাজ ar বিশেষত যখন 2+ মিলিয়ন ফাইলের কথা হয়। প্রশ্ন থেকে বিচ্যুতি ছাড়াই, সাধারণ ক্ষেত্রে যেমন এক স্তরের ডিরেক্টরি হিসাবে দ্রুত হয় তবে আপনি যদি ফাইল / ডিরেক্টরি কাঠামো পরিবর্তন করেন তবে তা স্থানান্তর করা আরও শক্ত হবে। সন্ধানের সাথে এবং এটি বিপুল পরিমাণে বিকল্পের সাথে আপনি আরও ভালভাবে প্রস্তুত হতে পারেন। তবুও আমি দৃ strongly়ভাবে পরামর্শ দিচ্ছি যে আপনি * এবং ব্যবহার করবেন না। পরিবর্তে সন্ধানের জন্য। এটি * এর চেয়ে বেশি পোর্টেবল হবে যেখানে আপনি হার্ডলিট নিয়ন্ত্রণ করতে পারবেন না ...
BitsOfNix

4
এটি প্রতি ফাইল প্রতি একটি প্রতিধ্বনি প্রক্রিয়া উত্সাহিত করবে (লুপের শেল থাকা অবস্থায় এটি প্রতিধ্বনি অন্তর্নির্মিত যা কোনও অতিরিক্ত প্রক্রিয়া না করেই ব্যবহৃত হবে), এবং ডিরেক্টরিতে নেমে আসবে, সুতরাং এটি অনেক ধীর হবে । এছাড়াও মনে রাখবেন যে এতে ডট ফাইল অন্তর্ভুক্ত থাকবে।
স্টাফেন চেজেলাস

আপনি ঠিক বলেছেন, আমি সর্বোচ্চ ১ টি যোগ করেছি যাতে এটি কেবল বর্তমান স্তরে আটকে থাকে।
BitsOfNix

7
find * -prune | while read f; do 
    echo "$f"
done

এর অকেজো ব্যবহার find- আপনি যা বলছেন তা কার্যকরভাবে "ডিরেক্টরি ( *) ডিরেক্টরিতে প্রতিটি ফাইলের জন্য , কোনও ফাইল খুঁজে পাবেন না। এছাড়াও, এটি বেশ কয়েকটি কারণে নিরাপদ নয়:

  • পাথগুলিতে ব্যাকস্ল্যাশগুলি -rবিকল্প ছাড়াও চিকিত্সা করা হয় read। এটি forলুপের সাথে কোনও সমস্যা নয় ।
  • পাথের নতুনলাইনগুলি লুপের অভ্যন্তরে কোনও তুচ্ছ ত্রুটিযুক্ত কার্যকারিতা ভেঙে দেবে। এটি forলুপের সাথে কোনও সমস্যা নয় ।

কোনও ফাইলের সাথে নাম হ্যান্ডেল findকরা কঠিন , সুতরাং forযখনই কেবল একা হয়ে সম্ভব হয় আপনার লুপ বিকল্পটি ব্যবহার করা উচিত । এছাড়াও, বাইরের প্রোগ্রামের মতো চালানো findসাধারণভাবে অভ্যন্তরীণ লুপ কমান্ড চালানোর চেয়ে ধীর হয় for


@ I0b0 'ফাইন্ড -পাথ' সম্পর্কে কি। ./* '-প্রিন-প্রিন্ট 0 | xargs -0 sh -c '...'?
অসমল্যাব

1
আমরাও findএর -print0কিংবা xargs' -0POSIX সামঞ্জস্যপূর্ণ হয়, এবং আপনি নির্বিচারে কমান্ড দূরে থাকতে পারে না sh -c ' ... ', (একক উদ্ধৃতি একক উদ্ধৃতি মধ্যে পলান যাবে না) তাই এটা বেশ এত সহজ নয়।
l0b0

4

তবে আমরা পারফরম্যান্স প্রশ্নের জন্য সফলতা! পরীক্ষার জন্য এই অনুরোধটি কমপক্ষে দুটি অনুমান করে যা এটি মারাত্মকভাবে বৈধ নয়।

উ: ধরে নিন যে তারা একই ফাইলগুলি খুঁজে পেয়েছে ...

ঠিক আছে, তারা প্রথমে একই ফাইলগুলি খুঁজে পাবে , কারণ তারা উভয়ই একই গ্লোব ধরে পুনরাবৃত্তি করছে, যথা *। তবে find * -prune | while read fবেশ কয়েকটি ত্রুটিগুলি ভুগছেন যা এটি সম্ভব করে তোলে এটি আপনার প্রত্যাশিত সমস্ত ফাইল খুঁজে পাবে না:

  1. POSIX সন্ধানটি একাধিক পাথ আর্গুমেন্ট গ্রহণ করার গ্যারান্টিযুক্ত নয়। বেশিরভাগ findবাস্তবায়নগুলি করে, কিন্তু তবুও, আপনার এটির উপর নির্ভর করা উচিত নয়।
  2. find *আপনি আঘাত যখন ভাঙ্গতে পারে ARG_MAXfor f in *না, কারণ ARG_MAXপ্রযোজ্য exec, বিল্টিনগুলিতে নয়।
  3. while read fফাইলের নাম দিয়ে শুরু করতে এবং সাদা জায়গার সাথে শেষ করে ভাঙ্গতে পারে, যা বন্ধ হয়ে যাবে। আপনি while readএটির এবং এর ডিফল্ট প্যারামিটার দিয়ে এটি কাটিয়ে উঠতে পারেন REPLY, তবে এটি নতুন লাইনের সাথে ফাইলের নামগুলির ক্ষেত্রে আসে না।

বি echo। কেউ শুধু ফাইলের নাম প্রতিধ্বনি করতে এটি করতে যাচ্ছে না। আপনি যদি এটি চান তবে এইগুলির মধ্যে একটি করুন:

printf '%s\n' *
find . -mindepth 1 -maxdepth 1 # for dotted names, too

whileএখানে লুপের পাইপটি একটি অন্তর্নিহিত সাবশেল তৈরি করে যা লুপ শেষ হয়ে গেলে বন্ধ হয় যা কারওর জন্য অপ্রয়োজনীয় হতে পারে।

প্রশ্নের উত্তর দিতে, এখানে আমার ডিরেক্টরিতে ফলাফল রয়েছে যা এতে 184 ফাইল এবং ডিরেক্টরি রয়েছে।

$ time bash -c 'for i in {0..1000}; do find * -prune | while read f; do echo "$f"; done >/dev/null; done'

real    0m7.998s
user    0m5.204s
sys 0m2.996s
$ time bash -c 'for i in {0..1000}; do for f in *; do echo "$f"; done >/dev/null; done'

real    0m2.734s
user    0m2.553s
sys 0m0.181s
$ time bash -c 'for i in {0..1000}; do printf '%s\n' * > /dev/null; done'

real    0m1.468s
user    0m1.401s
sys 0m0.067s

$ time bash -c 'for i in {0..1000}; do find . -mindepth 1 -maxdepth 1 >/dev/null; done '

real    0m1.946s
user    0m0.847s
sys 0m0.933s

লুপটি সাবসেল তৈরি করার সময় আমি এই বিবৃতিতে একমত নই - সবচেয়ে খারাপ ক্ষেত্রে, একটি নতুন থ্রেড: নীচেরগুলি আগে এবং পরে দেখাতে চেষ্টা করছে, খারাপ ফর্ম্যাটিংয়ের জন্য ক্ষমা চাইছে$ ps ax | grep bash 20784 pts/1 Ss 0:00 -bash 20811 pts/1 R+ 0:00 grep bash $ while true; do while true; do while true; do while true; do while true; do sleep 100; done; done; done; done; done ^Z [1]+ Stopped sleep 100 $ bg [1]+ sleep 100 & $ ps ax | grep bash 20784 pts/1 Ss 0:00 -bash 20924 pts/1 S+ 0:00 grep bash
ফিলি

প্রযুক্তিগতভাবে আমি ভুল বানান: পাইপটি অন্তর্নিহিত সাবশেলের কারণ করে, সময় লুপের জন্য নয় not আমি সম্পাদনা করব।
কোজিরো

2

find *সঠিকভাবে কাজ করবে না যদি *টোকেনগুলি তৈরি করে যা পাথের চেয়ে পূর্বাভাসের মতো দেখায়।

এটি --ঠিক করার জন্য আপনি সাধারণ তর্কটি ব্যবহার করতে পারবেন না কারণ --বিকল্পগুলির সমাপ্তি নির্দেশ করে এবং অনুসন্ধানের বিকল্পগুলি পথের আগে চলে আসে।

এই সমস্যাটি ঠিক করতে আপনি find ./*পরিবর্তে ব্যবহার করতে পারেন । তবে তারপরেও ঠিক একই স্ট্রিং উত্পাদন হচ্ছে না for x in *

নোট যে find ./* -prune | while read f ..আসলে এর স্ক্যানিং কার্যকারিতা ব্যবহার করে না find। এটি গ্লোব্বিং সিনট্যাক্স ./*যা প্রকৃতপক্ষে ডিরেক্টরিটিকে অনুসরণ করে এবং নামগুলি উত্পন্ন করে। তারপরে findপ্রোগ্রামটি statসেই সমস্ত নামের প্রত্যেকটিতে অন্তত একটি চেক করতে হবে । আপনার প্রোগ্রামটি চালু করার ও এটিতে এই ফাইলগুলি অ্যাক্সেস করার ওভারহেড রয়েছে এবং তার ফলাফলটি পড়তে I / O করছেন /

এটির চেয়ে কম দক্ষ ছাড়াও কীভাবে এটি হতে পারে তা কল্পনা করা শক্ত for x in ./* ...


1

সূচনাকারীদের জন্য forহ'ল শেল কীওয়ার্ড, বাশের মধ্যে অন্তর্নির্মিত, অন্যদিকে findপৃথক নির্বাহযোগ্য।

$ type -a for
for is a shell keyword

$ type -a find
find is /usr/bin/find

forযখন এটি বিস্তৃতি লুপ শুধুমাত্র globstar চরিত্র থেকে ফাইল পাবেন, এটা খুঁজে বের করে কোন ডিরেক্টরি মধ্যে recurse করা হবে না।

Otherhand এছাড়াও globstar দ্বারা প্রসারিত একটি তালিকা দেওয়া হবে এই তে কিন্তু এটা recursively মাধ্যমে প্রতিটি এক এই সম্প্রসারিত তালিকা এবং নল নীচের সমস্ত ফাইল ও ডিরেক্টরিগুলি পাবেন whileলুপ।

এই উভয় পদ্ধতিরই দিকটি বিপজ্জনক বলে বিবেচিত হতে পারে যে তারা কোনও পাথ বা ফাইলের নামগুলি ফাঁক করে না handle

এই 2 টি পদ্ধতির বিষয়ে আমি মন্তব্য করার মতো মূল্যবোধ সম্পর্কে ভাবতে পারি।


আমি ফাইন্ড কমান্ডে প্রিন্ট যুক্ত করেছি, তাই তারা আরও সমান হয়।
rubo77

0

যদি সন্ধানে ফিরে আসা সমস্ত ফাইল একক কমান্ড দ্বারা প্রক্রিয়া করা যায় (স্পষ্টত আপনার প্রতিধ্বনির উদাহরণ উপরে প্রযোজ্য নয়), আপনি xargs ব্যবহার করতে পারেন:

find * |xargs some-command

0

কয়েক বছর ধরে আমি এটি ব্যবহার করে আসছি: -

find . -name 'filename'|xargs grep 'pattern'|more

নির্দিষ্ট ফাইলগুলি (যেমন * .txt) সন্ধানের জন্য এমন একটি প্যাটার্ন রয়েছে যা গ্রেপ এটির জন্য আরও বেশি পাইপ করতে পারে যাতে এটি স্ক্রিনের বাইরে স্ক্রোল না হয়। কখনও কখনও আমি >> পাইপ ব্যবহার করে অন্য ফাইলটিতে ফলাফল লেখার জন্য যা আমি পরে দেখতে পারি।

ফলাফলের একটি নমুনা এখানে:

./Documents/Organ_docos/Rodgerstrio321A/rodgersmylist/2008-August.txt:Message-ID: <A165CE5C-61C5-4794-8651-66F5678ABCBF@usit.net>
./Documents/Organ_docos/Rodgerstrio321A/rodgersmylist/2008-August.txt:In-Reply-To: <A165CE5C-61C5-4794-8651-66F5678ABCBF@usit.net>
./Documents/Organ_docos/Rodgerstrio321A/rodgersmylist/2008-August.txt:  <A165CE5C-61C5-4794-8651-66F5678ABCBF@usit.net>
./Documents/Organ_docos/Rodgerstrio321A/rodgersmylist/2008-August.txt:  <A165CE5C-61C5-4794-8651-66F5678ABCBF@usit.net>
./Documents/Organ_docos/Rodgerstrio321A/rodgersmylist/2008-August.txt:Message-ID: <448E53556A3F442ABC58203D6281923E@hypermax>
./Documents/Organ_docos/Rodgerstrio321A/rodgersmylist/2011-April.txt:URL: http://mylist.net/private/rodgersorganusers/attachments/20110420/3f
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.