সাবডাইরেক্টরিগুলির তালিকা পান যাতে একটি ফাইল থাকে যার নামে একটি স্ট্রিং থাকে


45

যার নাম একটি নির্দিষ্ট প্যাটার্নের সাথে মেলে এমন একটি ফাইল রয়েছে এমন উপ-ডিরেক্টরিগুলির একটি তালিকা আমি কীভাবে পেতে পারি?

আরও সুনির্দিষ্টভাবে, আমি ডিরেক্টরিগুলির সন্ধান করছি যা "চ" অক্ষর সহ একটি ফাইল রয়েছে যেখানে এই ফাইলটির নাম রয়েছে।

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

উত্তর:


43
find . -type f -name '*f*' | sed -r 's|/[^/]+$||' |sort |uniq

উপরেরগুলি বর্তমান ডিরেক্টরি ( .) এর নীচে সমস্ত ফাইল সন্ধান করে যা নিয়মিত ফাইল ( -type f) এবং fতাদের নামে ( -name '*f*') কোথাও রয়েছে । এরপরে, sedকেবলমাত্র ডিরেক্টরি নাম রেখে ফাইলের নাম সরিয়ে দেয়। তারপরে, ডিরেক্টরিগুলির তালিকা সাজানো ( sort) এবং সদৃশ ( uniq) মুছে ফেলা হয় ।

sedকমান্ড একটি একক বিকল্প নিয়ে গঠিত। এটি নিয়মিত প্রকাশের সাথে ম্যাচগুলির সন্ধান করে /[^/]+$এবং কিছুই মিলে না এমন কিছু মিলিয়ে প্রতিস্থাপন করে। ডলার সাইন মানে লাইন শেষ। [^/]+'এর অর্থ এক বা একাধিক অক্ষর যা স্ল্যাশ নয়। সুতরাং, /[^/]+$চূড়ান্ত স্ল্যাশ থেকে রেখার শেষ পর্যন্ত সমস্ত অক্ষর। অন্য কথায়, এটি পুরো পথের শেষে ফাইলের নামের সাথে মেলে। সুতরাং, sed কমান্ড ফাইলের নামটি অপসারণ করে ফাইলটি যে ডিরেক্টরিটিতে ছিল সেটির নাম অপরিবর্তিত রেখে দেয়।

Simplifications

অনেক আধুনিক sortকমান্ড একটি -uপতাকা সমর্থন করে যা uniqঅপ্রয়োজনীয় করে তোলে । জিএনইউ সিডের জন্য:

find . -type f -name '*f*' | sed -r 's|/[^/]+$||' |sort -u

এবং, ম্যাকোএস সেডের জন্য:

find . -type f -name '*f*' | sed -E 's|/[^/]+$||' |sort -u

এছাড়াও, যদি আপনার findকমান্ড এটি সমর্থন করে, findডিরেক্টরি ডিরেক্টরি সরাসরি মুদ্রণ করা সম্ভব । এটি এর প্রয়োজনীয়তা এড়িয়ে চলে sed:

find . -type f -name '*f*' -printf '%h\n' | sort -u

আরও শক্তিশালী সংস্করণ (জিএনইউ সরঞ্জামের প্রয়োজন)

উপরের সংস্করণগুলি ফাইলের নাম দ্বারা বিভ্রান্ত হবে যা নিউলাইনগুলিকে অন্তর্ভুক্ত করে। আরও শক্তিশালী সমাধান হল NUL- সমাপ্ত স্ট্রিংগুলিতে বাছাই করা:

find . -type f -name '*f*' -printf '%h\0' | sort -zu | sed -z 's/$/\n/'

আমার কাছে প্রচুর ফাইল রয়েছে যা সেগুলি খুব সাশ্রয়ী করে তোলে। নিক্ষেপ uniqমিশ্রণ মধ্যে পুনরাবৃত্তি লাইন ইতিমধ্যে অধিকার একে অপরের সাথে পরবর্তী সরিয়ে অনেক সাহায্য করে। find . -type f -name '*f*' -printf '%h\0' | uniq -z | sort -zu | tr '\0' '\n'। অথবা যদি আপনার সরঞ্জামগুলি কিছুটা বেশি পুরানো হয় তবে ইউনিকের কাছে -z বিকল্প নাও থাকতে পারে। find . -type f -name '*f*' -printf '%h\n' | uniq | sort -u
jbo5112

1
ম্যাকস ব্যবহারকারীগণ: উক্ত পতাকাটি -আর নয়। কোনও কারণে এটি-ই
ডেভিড

@ ডেভিড খুব সত্য -Eম্যাকোস-এর জন্য দেখানোর জন্য উত্তর আপডেট হয়েছে ।
1024

22

কেন এটি চেষ্টা করবেন না:

find / -name '*f*' -printf "%h\n" | sort -u

সেরা উত্তর. উপরের কিছু উত্তরের উপরে, উপরে পুরোপুরি পসিএক্স-সামঞ্জস্যপূর্ণ এবং বিশেষতম সংক্ষিপ্ত পাইপলাইন পুরস্কারও অর্জন করে :)।
এম

উপরের অন্যান্যদের তুলনায় কেউ এর বনামের সময়টি দেখতে দেখতে আমি আগ্রহী, কারণ আমি অনুভব করি যে এটি এখন পর্যন্ত সবচেয়ে দ্রুত।
dlamblin

4
@kkm আমি সম্মত এই সবচেয়ে ভালো সমাধান কিন্তু POSIX চশমা জন্যfind আসলে বেশ বিক্ষিপ্ত-হয় -printfঅপারেটর হয় না নির্দিষ্ট করা হয়েছে। এটি বিএসডি নিয়ে কাজ করে না find। সুতরাং, না "সম্পূর্ণরূপে POSIX সামঞ্জস্যপূর্ণ।" (যদিও sort -u পসিক্সে রয়েছে ))
ওয়াইল্ডকার্ড

8

এটি করার জন্য প্রয়োজনীয়ভাবে দুটি পদ্ধতি ব্যবহার করতে পারেন। একটি স্ট্রিংকে বিশ্লেষণ করবে এবং অন্যটি প্রতিটি ফাইলের মধ্যে কাজ করবে। স্ট্রিংটিকে পার্সিং করা এমন একটি সরঞ্জাম ব্যবহার করে যেমন grep,, sedবা awkস্পষ্টতই দ্রুত হতে চলেছে তবে এখানে একটি উদাহরণ রয়েছে যা উভয়ই দেখিয়েছে, পাশাপাশি আপনি কীভাবে 2 পদ্ধতিগুলিকে "প্রোফাইল" করতে পারেন।

নমুনা তথ্য

নীচের উদাহরণগুলির জন্য আমরা নিম্নলিখিত ডেটা ব্যবহার করব

$ touch dir{1..3}/dir{100..112}/file{1..5}
$ touch dir{1..3}/dir{100..112}/nile{1..5}
$ touch dir{1..3}/dir{100..112}/knife{1..5}

*f*ফাইলগুলি থেকে কিছু মুছুন dir1/*:

$ rm dir1/dir10{0..2}/*f*

পদ্ধতির # 1 - স্ট্রিংগুলির মাধ্যমে পার্সিং

এখানে আমরা নিম্নলিখিত সরঞ্জামগুলি ব্যবহার করতে, চলুন find, grepএবং sort

$ find . -type f -name '*f*' | grep -o "\(.*\)/" | sort -u | head -5
./dir1/dir103/
./dir1/dir104/
./dir1/dir105/
./dir1/dir106/
./dir1/dir107/

পদ্ধতির # 2 - ফাইলগুলি ব্যবহার করে পার্সিং করা

একই টুল শৃঙ্খল আগের মত এই সময় ছাড়া আমরা ব্যবহার হবেন dirnameপরিবর্তে grep

$ find . -type f -name '*f*' -exec dirname {} \; | sort -u | head -5
./dir1/dir103
./dir1/dir104
./dir1/dir105
./dir1/dir106
./dir1/dir107

দ্রষ্টব্য: উপরোক্ত উদাহরণগুলি head -5কেবলমাত্র এই উদাহরণগুলির জন্য আমরা যে পরিমাণ আউটপুট নিয়ে কাজ করছি তা সীমাবদ্ধ করতে ব্যবহার করছি। আপনার সম্পূর্ণ তালিকা পেতে এগুলি সাধারণত সরানো হবে!

ফলাফল তুলনা

আমরা timeদুটি পদ্ধতির দিকে একবার নজর দিতে ব্যবহার করতে পারি ।

dirname

real        0m0.372s
user        0m0.028s
sys         0m0.106s

, grep

real        0m0.012s
user        0m0.009s
sys         0m0.007s

সুতরাং সম্ভব হলে স্ট্রিংগুলি মোকাবেলা করা সর্বদা সেরা best

বিকল্প স্ট্রিং বিশ্লেষণ পদ্ধতি

গ্রেপ এবং পিসিআরই

$ find . -type f -name '*f*' | grep  -oP '^.*(?=/)' | sort -u

sed

$ find . -type f -name '*f*' | sed 's#/[^/]*$##' | sort -u

awk

$ find . -type f -name '*f*' | awk -F'/[^/]*$' '{print $1}' | sort -u

+1 টি কারণ এটা কাজ করে, কিন্তু মজার ব্যাপার এই অনেকবার চেয়ে @ John1024 এর উত্তর বেশী সময় লাগে
Muhd

@ মুহ্দ - হ্যাঁ নামকরণের কলগুলি ধীর। আমি একটি বিকল্প নিয়ে কাজ করছি।
slm


1

এই উত্তরটি নির্লজ্জভাবে slm উত্তরের উপর ভিত্তি করে। এটি একটি আকর্ষণীয় পদ্ধতির ছিল, তবে ফাইল এবং / অথবা ডিরেক্টরি নামের বিশেষ অক্ষর (স্পেস, আধা-কলাম ...) থাকলে এর একটি সীমাবদ্ধতা থাকে। একটি ভাল অভ্যাস ব্যবহার করা হয় find /somewhere -print0 | xargs -0 someprogam

নমুনা তথ্য

নীচের উদাহরণগুলির জন্য আমরা নিম্নলিখিত ডেটা ব্যবহার করব

mkdir -p dir{1..3}/dir\ {100..112}
touch dir{1..3}/dir\ {100..112}/nile{1..5}
touch dir{1..3}/dir\ {100..112}/file{1..5}
touch dir{1..3}/dir\ {100..112}/kni\ fe{1..5}

*f*ফাইলগুলি থেকে কিছু মুছুন dir1/*/:

rm dir1/dir\ 10{0..2}/*f*

পদ্ধতির # 1 - ফাইলগুলি ব্যবহার করে পার্সিং করা

$ find -type f -name '*f*' -print0 | sed -e 's#/[^/]*\x00#\x00#g' | sort -zu | xargs -0 -n1 echo | head -n5
./dir1/dir 103
./dir1/dir 104
./dir1/dir 105
./dir1/dir 106
./dir1/dir 107

দ্রষ্টব্য : উপরোক্ত উদাহরণগুলি head -5কেবলমাত্র এই উদাহরণগুলির জন্য আমরা যে পরিমাণ আউটপুট নিয়ে কাজ করছি তা সীমাবদ্ধ করতে ব্যবহার করছি। আপনার সম্পূর্ণ তালিকা পেতে এগুলি সাধারণত সরানো হবে! এছাড়াও, echoআপনি যে কমান্ডটি ব্যবহার করতে চান তা প্রতিস্থাপন করুন ।


আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.