পুনরাবৃত্তভাবে কেবল একটি ডিরেক্টরিতে নির্দিষ্ট ফাইলের নামটিতে কোনও প্যাটার্ন / পাঠ্য অনুসন্ধান করুন?


16

আমার একটি ডিরেক্টরি রয়েছে (যেমন, abc/def/efg) অনেকগুলি উপ-ডিরেক্টরি (যেমন , abc/def/efg/(1..300):)। এই সাব-ডিরেক্টরিগুলির মধ্যে একটি সাধারণ ফাইল রয়েছে (যেমন, file.txt)। আমি কেবল file.txtঅন্য ফাইলগুলি বাদ দিয়ে একটি স্ট্রিং অনুসন্ধান করতে চাই । কিভাবে আমি এটি করতে পারব?

আমি ব্যবহার করেছি grep -arin "pattern" *, তবে আমাদের কাছে অনেক উপ-ডিরেক্টরি এবং ফাইল থাকলে এটি খুব ধীর হয়।


উত্তর:


21

মূল ডিরেক্টরিতে, আপনি কেবল তখন সেই ফাইলগুলিতে ব্যবহার করতে পারেন findএবং চালাতে পারেন grep:

find . -type f -iname "file.txt" -exec grep -Hi "pattern" '{}' +

2
আমিও পাশ করার পরামর্শ দিই -Hকরতে grepযাতে, মামলা যখন শুধুমাত্র একটি পাথ এটি পাস করা হয়েছে, সেই পথ এখনও ছাপা হয় (বরং ফাইল থেকে মাত্র ম্যাচিং লাইন চেয়ে)।
এলিয়াহ কাগন

24

আপনি গ্লোবস্টারও ব্যবহার করতে পারেন।

জানার জবাব অনুসারে বিল্ডিং grepকমান্ডfind হ'ল এটি করার একটি অত্যন্ত শক্তিশালী, বহুমুখী এবং বহনযোগ্য উপায় ( সুডোডাসের উত্তরও দেখুন )। আর muru ব্যবহারের একটি চমৎকার পদ্ধতির পোস্ট করেছে grep'র --includeবিকল্প । তবে আপনি যদি কেবল grepকমান্ড এবং আপনার শেলটি ব্যবহার করতে চান তবে এটি করার আরও একটি উপায় রয়েছে - আপনি শেলটি নিজেই প্রয়োজনীয় পুনরাবৃত্তি সম্পাদন করতে পারেন :

shopt -s globstar   # you can skip this if you already have globstar turned on
grep -H 'pattern' **/file.txt

-Hপতাকা তোলে grepফাইলের নাম এমনকি যদি শুধুমাত্র একটি ম্যাচিং ফাইল পাওয়া যায় প্রদর্শন করুন। আপনি পাস করতে পারেন -a, -iএবং -nপতাকা (আপনার উদাহরণ থেকে) grepপাশাপাশি, যদি যে আপনার যা প্রয়োজন। তবে পাস করবেন না -rবা -Rএই পদ্ধতিটি ব্যবহার করার সময়। এটা শেল যে উল্লিখিত glob ধারণকারী প্যাটার্ন সম্প্রসারণে ডিরেক্টরি recurses **, এবং নাgrep

এই নির্দেশাবলী বাশ শেলের সাথে সুনির্দিষ্ট। উশুন্টুতে ব্যাশ হ'ল ডিফল্ট ব্যবহারকারী শেল (এবং বেশিরভাগ অন্যান্য জিএনইউ / লিনাক্স অপারেটিং সিস্টেম), সুতরাং আপনি যদি উবুন্টুতে থাকেন এবং আপনার শেলটি কী তা জানেন না তবে এটি অবশ্যই বাশ Bash যদিও জনপ্রিয় শেলগুলি সাধারণত ডিরেক্টরি-ট্র্যাভারিং **গ্লোবগুলিকে সমর্থন করে , তারা সবসময় একইভাবে কাজ করে না। আরো তথ্যের জন্য, দেখুন Stéphane Chazelas এর চমৎকার উত্তর করতে ম ফল *, ম ** এবং ম *** উপর Unix.SE

কিভাবে এটা কাজ করে

চালু করলে তা globstar ব্যাশ শেল বিকল্প তোলে **ম্যাচ ডিরেক্টরির বিভাজক ধারণকারী পাথ ( /)। এটি একটি ডিরেক্টরি পুনরাবৃত্তি গ্লোব। বিশেষত, হিসাবে man bashব্যাখ্যা:

যখন গ্লোবস্টারের শেল বিকল্পটি সক্ষম করা থাকে, এবং * কোনও পথের নাম প্রসারণ প্রসঙ্গে ব্যবহৃত হয়, তখন একক প্যাটার্ন হিসাবে ব্যবহৃত দুটি সংলগ্ন * গুলি সমস্ত ফাইল এবং শূন্য বা আরও ডিরেক্টরি এবং সাব ডিরেক্টরিতে মিলবে। যদি একটি / দ্বারা অনুসরণ করা হয় তবে দুটি সংলগ্ন * গুলি কেবল ডিরেক্টরি এবং উপ-ডিরেক্টরিগুলির সাথে মিলবে।

আপনার এটি সম্পর্কে সতর্ক হওয়া উচিত, যেহেতু আপনি যে কমান্ডগুলি চালিয়ে যেতে পারেন যা আপনার ইচ্ছার চেয়ে অনেক বেশি ফাইল সংশোধন বা মুছতে পারে, বিশেষত আপনি **যখন লিখতে চেয়েছিলেন তখন লেখেন *। (এটি এই কমান্ডে নিরাপদ, যা কোনও shopt -u globstarআইল পরিবর্তন করে না)) গ্লোবস্টারের শেল বিকল্পটি আবার বন্ধ করে দেয়।

গ্লোবস্টার এবং এর মধ্যে কয়েকটি ব্যবহারিক পার্থক্য রয়েছে find

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

উপরের পদ্ধতিটি ডিরেক্টরিগুলির ভিতরে দেখতে পারে না যার নাম a দিয়ে শুরু হয় .। কখনও কখনও আপনি এই জাতীয় ফোল্ডার পুনরাবৃত্তি করতে চান না, তবে কখনও কখনও আপনি তা করেন।

একটি সাধারণ গ্লোবের মতো, শেলটি সমস্ত মিলের পাথের একটি তালিকা তৈরি করে এবং সেগুলি grepবিশ্বব্যাপী নিজের জায়গায় আপনার কমান্ডের ( ) আর্গুমেন্ট হিসাবে দেয়। যদি আপনার কাছে এমন অনেকগুলি ফাইল বলা হয়ে থাকে file.txtযে ফলস্বরূপ কমান্ডটি সিস্টেমটি কার্যকর করতে খুব দীর্ঘ হয় তবে উপরের পদ্ধতিটি ব্যর্থ হবে। অনুশীলনে আপনার (কমপক্ষে) হাজার হাজার ফাইলের প্রয়োজন ছিল, তবে এটি ঘটতে পারে।

যে পদ্ধতিগুলি ব্যবহার করে findসেগুলি এই বিধিনিষেধের সাপেক্ষ নয়, কারণ:

  • Zanna এর উপায়grep সম্ভাব্য অনেক পাথ আর্গুমেন্ট সহ একটি কমান্ড তৈরি করে এবং পরিচালনা করে । তবে যদি একটি ফাইলকে আরও একটি তালিকাতে তালিকাবদ্ধ করা যায় তার চেয়ে বেশি ফাইল খুঁজে পাওয়া যায়, তবে +নির্ধারিত -execকর্মটি কয়েকটি পাথ দিয়ে কমান্ডটি চালায়, তারপরে আবার আরও কয়েকটি পথ দিয়ে চালায় এবং আরও কিছু করে। grepএকাধিক ফাইলে স্ট্রিংয়ের জন্য আইংয়ের ক্ষেত্রে, এটি সঠিক আচরণ করে।

    এখানে আচ্ছন্ন করা গ্লোবস্টারের পদ্ধতির মতো, এটি প্রতিটি মিলিয়ে পাথগুলি সহ সমস্ত মিলিত লাইনগুলি মুদ্রণ করে।

  • সুডোডাসের পথgrep প্রতিটি সন্ধানের জন্য পৃথকভাবে চলে file.txt। যদি অনেকগুলি ফাইল থাকে তবে এটি অন্য কয়েকটি পদ্ধতির তুলনায় ধীর হতে পারে তবে এটি কার্যকর হয়।

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

সাথে রঙিন হচ্ছে find

গ্লোবস্টার ব্যবহারের তাত্ক্ষণিক সুবিধাগুলির মধ্যে একটি হ'ল, উবুন্টুতে ডিফল্টরূপে বর্ণযুক্ত grepআউটপুট তৈরি করা হবে। কিন্তু আপনি সহজেই এই সঙ্গে পেতে পারেন find, অত্যধিক

ব্যবহারকারী উবুন্টু সঙ্গে নির্মিত অ্যাকাউন্ট উপনাম করে তোলে grepসত্যিই চালানো grep --color=auto(রান alias grepদেখতে)। এটি একটি ভাল জিনিস যে আপনি ব্যক্তিগতভাবে ইন্টারঅ্যাকটিভভাবে ইস্যু করার সময় এ্যালিয়াসগুলি প্রসারিতভাবে প্রসারিত হবে তবে এর অর্থ হ'ল আপনি যদি পতাকাটির সাথে findডাকতে চান তবে আপনাকে এটি স্পষ্টভাবে লিখতে হবে। উদাহরণ স্বরূপ:grep--color

find . -name file.txt -exec grep --color=auto -H 'pattern' {} +

আপনি আরও পরিষ্কারভাবে বলতে চাইবেন যে এটি bashকাজ করার জন্য আপনাকে শেলটি ব্যবহার করা উচিত । আপনি কি এটা বলতে পরোক্ষভাবে "globstar ব্যাশ শেল বিকল্প" এ কিন্তু এটি সহজে খুব দ্রুত পড়া মানুষ মিস করা যাবে না।
স্টিগ হেমার

আমি আমার উত্তরটি সরিয়েছি কারণ এটি অনেক সমালোচনামূলক মন্তব্যের কারণ হয়েছিল। সুতরাং আপনার উত্তরে এর উল্লেখটি সরিয়ে নেওয়া উচিত।
সুডোডাস

@ স্টিটিহেমার ধন্যবাদ - আমি স্পষ্ট করে দিয়েছি যে সমস্ত শেলের এই বৈশিষ্ট্যটি নেই। যদিও অনেক শেল (কেবল বাশ নয়) ডিরেক্টরি- ট্র্যাভারিং গ্লোবগুলিকে সমর্থন করে **, আপনার মূল সমালোচনা সঠিক: **এই উত্তরের উপস্থাপনা বাশের সাথে নির্দিষ্ট, কেবল শট কেবল বাশ এবং "গ্লোবস্টার" শব্দটি বাশ এবং আমার মনে হয় কেবল tcsh। আমি মূলত এই জটিলতার কারণে এটিকে ঘটিয়েছিলাম তবে আপনি ঠিক বলেছেন যে এটি কিছুটা বিভ্রান্তিকর। এই উত্তরে দৈর্ঘ্যে এটি আলোচনা করার পরিবর্তে আমি অন্য একটি (বেশ পুঙ্খানুপুঙ্খ) পোস্টে লিঙ্ক করেছি যা ভারী উত্তোলন করে।
এলিয়াহ কাগন

@ সুদোডাস আমি এটি করেছি তবে আমি আশা করি এটি অস্থায়ী। আমি এবং অন্যান্যরা আপনার উত্তরটিকে মূল্যবান বলে মনে করেছি। এটি সত্য -eযে পাথগুলিতে প্রয়োগ করা উচিত নয়, তবে এটি সহজেই স্থির হয়ে গেছে। প্রথম কমান্ডের জন্য, কেবল বাদ দিন -e। দ্বিতীয় জন্য, ব্যবহার করুন find . -name file.txt -printf $'\e[32m%p:\e[0m\n' -exec grep -i "pattern" {} \;বা find . -name file.txt -exec printf '\e[32m%s:\e[0m\n' {} \; -exec grep -i "pattern" {} \;। ব্যবহারকারীরা কখনও কখনও -eঅন্যদের কাছে আপনার উপায়কে ( ব্যবহারের সাথে স্থির করে) পছন্দ করবেন, যা প্রতি ম্যাচের প্রতি লাইনে একটি পাথ প্রিন্ট করে ; আপনার ফলাফল অনুসারে ফাইলের প্রতি এক পাথ মুদ্রণ করে grep
এলিয়াহ কাগন

@ সুদোদাস তাই আপনি যা করছেন তা grepনিজেই করবেন না । অন্য কিছু সমালোচনাও ভুল ছিল। grep -Hদ্বারা চালিত (বা ) -execছাড়া রঙিন হবে না । আইইইই 1003.1-2008 নিশ্চয়তা দেয় না যে বিস্তৃতি কিন্তু উবুন্টু হয়েছে গনুহ খুঁজুন, যা করেআপনার সাথে যদি ঠিক থাকে তবে আমি বাগটি ঠিক করার জন্য আপনার পোস্টটি সম্পাদনা করব (এবং এর ব্যবহারের বিষয়টি পরিষ্কার করুন) এবং আপনি মুছে ফেলতে চান কিনা তা দেখতে পারেন। (মুছে ফেলা পোস্টগুলি দেখতে / সম্পাদনা করার জন্য আমার কাছে প্রতিনিধি রয়েছে))--colorGREP_COLOR{}##### {}:-e
এলিয়াহ কাগন

18

আপনার এটার দরকার নেই find; grepএটি পুরোপুরি সূক্ষ্মটি নিজের মতো করে পরিচালনা করতে পারে:

grep "pattern" . -airn --include="file.txt"

থেকে man grep:

--exclude=GLOB
      Skip  files  whose  base  name  matches  GLOB  (using   wildcard
      matching).   A  file-name  glob  can  use  *,  ?,  and [...]  as
      wildcards, and \ to quote  a  wildcard  or  backslash  character
      literally.

--exclude-from=FILE
      Skip  files  whose  base name matches any of the file-name globs
      read from FILE  (using  wildcard  matching  as  described  under
      --exclude).

--exclude-dir=DIR
      Exclude  directories  matching  the  pattern  DIR from recursive
      searches.

--include=GLOB
      Search  only  files whose base name matches GLOB (using wildcard
      matching as described under --exclude).

ভাল - এটি সেরা উপায় মত মনে হচ্ছে। সহজ এবং দক্ষ। আমি যদি এই পদ্ধতিটি সম্পর্কে জানতাম (বা ম্যানপেজটি পরীক্ষা করার জন্য ভাবা হয়েছিল)। ধন্যবাদ!
এলিয়াহ কাগন

@ এলিয়াকাগান আমি আরও অবাক হয়েছি জান্না এটি পোস্ট করেননি - কিছুক্ষণ আগে আমি অন্য উত্তরের জন্য এই বিকল্পের একটি উদাহরণ দেখিয়েছি। :)
মুরু

2
ধীরে ধীরে শেখা, হায়, তবে আমি অবশেষে সেখানে পৌঁছেছি, আপনার শিক্ষাগুলি আমার উপর সম্পূর্ণভাবে নষ্ট হয় না;)
জান্না

এটি খুব সহজ এবং মনে রাখা সহজ। ধন্যবাদ.
রাজেশ কেলাদিমাথ

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

8

পদ্ধতি দেওয়া muru এর উত্তর , চলমান grepসঙ্গে --includeএকটি ফাইল নির্দিষ্ট করার পতাকা, প্রায়ই সেরা পছন্দ। তবে এটি দিয়েও করা যায় find

এই উত্তরের পদ্ধতির সন্ধান পাওয়া প্রতিটি ফাইলের জন্য পৃথকভাবে findচালানো ব্যবহার করা হয় grepএবং প্রতিটি ফাইলের সাথে মিলিত লাইনগুলির উপরে প্রতিটি ফাইলের পাথটি ঠিক একবার মুদ্রণ করে । (প্রতিটি ম্যাচের লাইনের সামনে যে পদ্ধতিটি মুদ্রণ করে সেগুলি অন্য উত্তরে areাকা থাকে))


আপনি যে ডিরেক্টরিতে এই ফাইলগুলি রয়েছে সেখানে আপনি ডিরেক্টরি ট্রি গাছের শীর্ষে ডিরেক্টরি পরিবর্তন করতে পারেন। তারপরে চালান:

find . -name "file.txt" -type f -exec echo "##### {}:" \; -exec grep -i "pattern" {} \;

এটি .নামের প্রতিটি ফাইলের পাথ (বর্তমান ডিরেক্টরিটির তুলনায় , এবং ফাইলটির নাম নিজেই অন্তর্ভুক্ত) মুদ্রণ করে file.txt, তারপরে ফাইলের সমস্ত মিলে যাওয়া লাইন। এটি কাজ করে কারণ {}পাওয়া ফাইলের জন্য স্থানধারক। প্রতিটি ফাইলের পাথ উপসর্গযুক্ত হয়ে এর বিষয়বস্তুগুলি থেকে আলাদা করা হয় #####এবং কেবলমাত্র একবার মুদ্রিত হয় that ফাইলটির সাথে ম্যাচের লাইনের আগে। ( file.txtযে ফাইলগুলিতে কোনও ম্যাচ নেই সেগুলিতে এখনও তাদের পাথগুলি মুদ্রিত থাকে)) প্রতিটি মিলিত লাইনের শুরুতে কোনও পাথ মুদ্রিত পদ্ধতিগুলির চেয়ে আপনি এই আউটপুটটি কম বিশৃঙ্খলা পেতে পারেন।

ব্যবহার findভালো প্রায় সবসময় দ্রুত চলমান চেয়ে থাকবে grepউপর যে ফাইল ( grep -arin "pattern" *,) কারণ findসঠিক নাম ফাইল এর জন্য অনুসন্ধান এবং সমস্ত অন্যান্য ফাইল অগ্রাহ্য।

উবুন্টু গনুহ খোঁজ ব্যবহার , যা সবসময় বিস্তৃতি {}এমনকি যখন এটা একটি বৃহত্তর স্ট্রিং দেখা , মত ##### {}:। আপনার যদি আপনার কমান্ডের দরকার হয় এমন সিস্টেমে কাজ করার জন্য যা findএটি সমর্থন করে না , বা আপনি -execযখন একেবারে প্রয়োজন তখনই এই ক্রিয়াটি ব্যবহার করতে পছন্দ করেন , আপনি ব্যবহার করতে পারেন:

find . -name "file.txt" -type f -printf '##### %p:\n' -exec grep -i "pattern" {} \;

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

find . -name file.txt -printf $'\e[32m%p:\e[0m\n' -exec grep -i "pattern" {} \;

যে আপনার শেল ঘটায় ঘুরে পালাবার কোড প্রকৃত পালাবার ক্রম যে একটি টার্মিনাল সবুজ উত্পাদন করে বা সবুজ জন্য, এবং স্বাভাবিক রঙ জন্য পালাবার কোড সহ একই জিনিস না। এই পলায়নগুলি পাস করা হয় find, যা এটি কোনও ফাইলের নাম মুদ্রণের সময় ব্যবহার করে। ( $' 'উদ্ধৃতি কারণ এখানে প্রয়োজনীয় find'র -printfকর্ম না চেনে \eব্যাখ্যা ANSI পালাবার কোডগুলি।)

যদি আপনি চান, আপনি যদি এর পরিবর্তে ব্যবহার করতে পারে -execসঙ্গে সিস্টেমের printfকমান্ড (যা সমর্থন করে \e)। সুতরাং একই জিনিসটি করার আরেকটি উপায় হ'ল:

find . -name file.txt -exec printf '\e[32m%s:\e[0m\n' {} \; -exec grep -i "pattern" {} \;

আমি একটি অ্যারে দিয়ে একটি "লুপ" তৈরি করতে যাচ্ছিলাম এবং আমি অনুসন্ধান থেকে এক্সিকিউট নেটিভ বিকল্প সম্পর্কে ভাবি নি। ভাল একটা! তবে আমি মনে করি যে বিন্দু ব্যবহার করে আপনি যে ডিরেক্টরিটি ইতিমধ্যে রয়েছেন সেখানে আপনাকে সনাক্ত করবে। আমি ভুল হলে আমাকে সংশোধন করুন। অনুসন্ধানের ক্রমে সরাসরি পার্স করার জন্য এটি নির্দিষ্ট করে দেওয়া কি ভাল হবে না? find abc/def/efg -name "file.txt" -type f -exec echo -e "##### {}:" \; -exec grep -i "pattern" {} \;
কেসিডিটিভি

অবশ্যই, এটি cd abc/def/efg'পরিবর্তন ডিরেক্টরি' কমান্ডটি সরিয়ে
ফেলবে

(1) আপনি কেন -eবিকল্পটি নির্দিষ্ট করছেন echo? এটি ব্যাকস্ল্যাশগুলি ধারণ করে এমন কোনও ফাইলের নাম ম্যাঙ্গাল করে দেবে। (২) যুক্তির অংশ{} হিসাবে ব্যবহার করা কাজের গ্যারান্টিযুক্ত নয়। বলা ভাল বা হবে । (3) কেন শুধু ব্যবহার বা না ? (4) এছাড়াও বিবেচনা করুন । -exec echo "#####" {} \;-exec printf "##### %s:\n" {} \;-print-printfgrep -H
জি-ম্যান 21

@ জি-ম্যান, ১) কারণ আমি এএনএসআই রঙটি মূলত ব্যবহার করেছি: find . -name "file.txt" -type f -exec echo -e "\0033[32m{}:\0033[0m" \; -exec grep -i "pattern" {} \;২) আপনি ঠিক থাকতে পারেন, তবে এখনও পর্যন্ত এটি আমার পক্ষে কাজ করছে। 3) -প্রিন্ট এবং -প্রিন্টফ এছাড়াও বিকল্প। 4) এটি ইতিমধ্যে মূল উত্তর আছে। - যাইহোক, আপনি নিজের উত্তর দিয়ে স্বাগত :-)
সুডডাস

আপনার দুটি -execকলের দরকার নেই । কেবল ব্যবহার করুন grep -Hএবং এটি ফাইলের নাম (রঙে) পাশাপাশি মেলে পাঠ্য মুদ্রণ করবে।
টেরডন

0

কেবল উল্লেখ করতে যে যদি প্রশ্নের শর্তগুলি সাহিত্যে নেওয়া যায় তবে আপনি সরাসরি গ্রেপ ব্যবহার করতে পারেন:

grep 'pattern' abc/def/efg/*/file.txt

অথবা

grep 'pattern' abc/def/efg/{1..300}/file.txt
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.