এমন একটি ডিরেক্টরি সন্ধান করুন যা কোনও ফাইল ধারণ করে না


58

হ্যাঁ, আমি আমার সংগীত বাছাই করছি। আমি নিম্নলিখিত মন্ত্রটিতে সবকিছু সুন্দরভাবে সাজিয়েছি: /Artist/Album/Track - Artist - Title.extএবং যদি এটি উপস্থিত থাকে তবে কভারটি ভিতরে বসে /Artist/Album/cover.(jpg|png)

আমি সমস্ত দ্বিতীয় স্তরের ডিরেক্টরিতে স্ক্যান করতে চাই এবং একটি কভার নেই এমন একটি সন্ধান করতে চাই। দ্বিতীয় স্তরের দ্বারা, আমি বোঝাতে চাইছি /Britney Spears/কভার.জেপজি না থাকলে আমি পাত্তা দিই না, তবে /Britney Spears/In The Zone/এটি না থাকলে আমি যত্ন করব ।

কভার-ডাউনলোডিং সম্পর্কে চিন্তা করবেন না (এটি আমার জন্য আগামীকাল একটি মজাদার প্রকল্প) আমি কেবল একটি বিপরীত-ইশ findউদাহরণ সম্পর্কে গৌরবময় বাশ-ফুয়েন্সি যত্ন করি ।


এমন যে কেউ কভার যে শুধু ইনস্টল অনুপস্থিত ডাউনলোড করার আগ্রহ দেখিয়েছে জন্য launchpad.net/coverlovin এবং প্রতিস্থাপন @phoibos মধ্যে -print সঙ্গে উত্তর "-exec ./coverlovin.py {} \;"
ভয়ঙ্কর কোহেন

উত্তর:


81

কেস 1: সঠিক ফাইলের নামটি সন্ধান করার জন্য আপনি জানেন

ব্যবহার করুন findসঙ্গে test -e your_fileযদি একটি ফাইল বিদ্যমান বার করো। উদাহরণস্বরূপ, আপনি ডিরেক্টরিগুলি সন্ধান করেন যার cover.jpgমধ্যে সেগুলি নেই:

find base_dir -mindepth 2 -maxdepth 2 -type d '!' -exec test -e "{}/cover.jpg" ';' -print

যদিও এটি কেস সেনসিটিভ।

কেস 2: আপনি আরও নমনীয় হতে চান

আপনি কেস সম্পর্কে নিশ্চিত নন, এবং এক্সটেনশনটি হতে পারে jPg, png...

find base_dir -mindepth 2 -maxdepth 2 -type d '!' -exec sh -c 'ls -1 "{}"|egrep -i -q "^cover\.(jpg|png)$"' ';' -print

ব্যাখ্যা:

  • আপনার shপ্রতিটি ডিরেক্টরিতে একটি শেল স্পোন করা প্রয়োজন যেহেতু ব্যবহারের সময় পাইপিং সম্ভব নয়find
  • ls -1 "{}"ডিরেক্টরিগুলির কেবলমাত্র ফাইলের নামগুলি findবর্তমানে আবর্তিত হচ্ছে out
  • egrep(পরিবর্তে grep) বর্ধিত নিয়মিত এক্সপ্রেশন ব্যবহার করে; -iঅনুসন্ধান কেসকে সংবেদনশীল করে -qতোলে, এটি কোনও আউটপুট বাদ দেয়
  • "^cover\.(jpg|png)$"অনুসন্ধানের ধরণ। এই উদাহরণে এটি মেলে যেমন cOver.png, Cover.JPGবা cover.png.অন্যথায় এটা মানে এটি মিলে যায় পলান করা আবশ্যক কোনো অক্ষর। ^রেখার শুরুটি, $এর শেষ চিহ্নিত করে

উদাহরণস্বরূপ অন্যান্য অনুসন্ধান প্যাটার্ন উদাহরণ :

egrep -i -q "^cover\.(jpg|png)$"অংশটি এর সাথে প্রতিস্থাপন করুন :

  • egrep -i -q "cover\.(jpg|png)$": এছাড়াও মেলে cd_cover.png, album_cover.JPG...
  • egrep -q "^cover\.(jpg|png)$": ম্যাচ cover.png, cover.jpgকিন্তু নয় Cover.jpg(কেস সংবেদনশীলতা বন্ধ করা হয় না)
  • egrep -iq "^(cover|front)\.jpg$": মেলে যেমন front.jpg, Cover.JPGতবে নয় Cover.PNG

এই আরো তথ্যের জন্য, চেক আউট রেগুলার এক্সপ্রেশন


একেবারে সুন্দর - সমস্যাটি যে কেস বা বিভিন্ন এক্সটেনশানগুলির মধ্যে বাছাই করা নমনীয় নয় (আমি ওয়াইল্ডকার্ড চেষ্টা করেছি তবে যাই না)। আমি এর চেয়ে ভাল বিকল্প আছে কিনা আমি অবাক test
অলি

1
হুম আপনি এটি দিয়ে বাসা বেঁধতে পারেন তবে এটি -exec bash -c '[[ -n $(find "{}" -iname "cover.*") ]]' \;অপটিমাইজেশনের দিক থেকে বেশ নোংরা। এটি যদিও কাজ করে।
অলি

আমি দেখতে পেয়েছি যে আপনি ওআর ক্যোয়ারীগুলির জন্য testএকটি প্রচুর পরিমাণ পাস করতে পারেন -o EXPRESSION... উদাহরণস্বরূপ: test -e "{}/cover.jpg" -o -e "{}/cover.png"এটি একটি সম্পূর্ণরূপে সজ্জিত অনুসন্ধানের চেয়ে ভাল তবে এটি এখনও সংবেদনশীল ক্ষেত্রে।
অলি

আমার মনে রাখা উচিত যে এটির দুটি তুলনামূলক তুলনায় (আমার শেষ মন্তব্য অনুসারে দুটি পরীক্ষা) তুলনা করা (দু'টি পরীক্ষা খুঁজে পেয়েছেন এবং গ্লোব্বিং খুঁজে পেয়েছেন) এটি এখন পর্যন্ত সবচেয়ে ধীর (যথাক্রমে 40ms এবং 50ms বনাম 684 মিমি)
অলি

মূল উত্তর-সলিউশনটি এক সেকেন্ডের সময় নেয় এবং সেই পরিস্থিতিতে বিরতি $ঘটে যা দির নামে রয়েছে (উদাহরণস্বরূপ কে $ হা)।
অলি

12

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

comm -3 \
    <(find ~/Music/ -iname 'cover.*' -printf '%h\n' | sort -u) \
    <(find ~/Music/ -maxdepth 2 -mindepth 2 -type d | sort) \
| sed 's/^.*Music\///'

হুররে.

নোট:

  • commএর যুক্তিগুলি নিম্নরূপ:

    • -1 ফাইল 1 এ অনন্য লাইনগুলি দমন করে
    • -2 ফাইলগুলিতে অনন্য লাইনগুলি দমন করুন
    • -3 উভয় ফাইলে প্রদর্শিত লাইনগুলি দমন করুন
  • commকেবল ফাইল নেয়, অতএব কুকি <(...)ইনপুট পদ্ধতি। এটি একটি বাস্তব [অস্থায়ী] ফাইলের মাধ্যমে সামগ্রীটি পাইপ করে।

  • commবাছাই করা ইনপুট দরকার বা এটি কাজ করে না এবং findকোনও অর্ডার দিয়ে গ্যারান্টি দেয় না। এটি অনন্য হতে হবে। প্রথম findক্রিয়াকলাপটি একাধিক ফাইল সন্ধান cover.*করতে পারে যাতে নকল এন্ট্রি থাকতে পারে। sort -uদ্রুত এগুলি একের দিকে নামিয়ে দেয়। দ্বিতীয় সন্ধানটি সর্বদা অনন্য হতে চলেছে।

  • dirnamesed(এট আল) অবলম্বন না করে কোনও ফাইলের দির পাওয়ার জন্য একটি সহজ সরঞ্জাম ।

  • findএবং commউভয়ই তাদের আউটপুট নিয়ে কিছুটা অগোছালো। sedজিনিসগুলি পরিষ্কার করার জন্য ফাইনাল রয়েছে যাতে আপনার সাথে বাকি থাকে Artist/Album। এটি আপনার পক্ষে পছন্দসই বা নাও হতে পারে।


2
আপনার প্রথমটিকে findসম্ভবত সহজতর করা যেতে পারে find ~/Music/ -iname 'cover.*' -printf '%h\n', প্রয়োজন এড়ানো dirname। যদিও dirnameঅন্য কোথাও সহজ।
টম

ধন্যবাদ @ টম, এটি অনেক দ্রুত যে সর্বত্র বেরিয়েছে (আমার সংগীত দিরের 29 মিমি বনাম 734 মিমি - "উভয়" উষ্ণ "খুঁজে পেয়েছে)
অলি

9

এটি সন্ধানের চেয়ে গ্লোববিংয়ের সাথে সমাধান করা অনেক সুন্দর।

$ cd ... # to the directory one level above the album/artist structure

$ echo */*/*.cover   # lists all the covers

$ printf "%s\n" */*/*.cover # lists all the covers, one per line

এখন ধরুন এই সুন্দর কাঠামোতে আপনার কাছে কোনও স্ট্রে ফাইল নেই। বর্তমান ডিরেক্টরিতে কেবল শিল্পী উপ-ডিরেক্টরি রয়েছে এবং সেগুলিতে কেবল অ্যালবামের উপ-ডিরেক্টরি থাকে। তারপরে আমরা এরকম কিছু করতে পারি:

$ diff  <(for x in */*/cover.jpg; do echo "$(dirname "$x")" ; done) <(printf "%s\n" */*)

<(...)সিনট্যাক্স ব্যাশ প্রক্রিয়া প্রতিকল্পন: এটি আপনি একটি ফাইল যুক্তি স্থানে কমান্ড ব্যবহার করতে দেয়। এটি আপনাকে একটি কমান্ডের আউটপুটটিকে ফাইল হিসাবে বিবেচনা করতে দেয়। সুতরাং আমরা দুটি প্রোগ্রাম চালাতে পারি এবং অস্থায়ী ফাইলগুলিতে তাদের আউটপুট সংরক্ষণ না করে তাদের ডিফ নিতে পারি। diffপ্রোগ্রামটি ভাবে যে দুই ফাইলগুলির সাথে কাজ করা হয়, কিন্তু এটি আসলে দুই পাইপ থেকে পড়া হচ্ছে।

কমান্ড যে ডান হাত ইনপুট উৎপন্ন diff, printf "%s\n" */*শুধু অ্যালবাম ডিরেক্টরি তালিকাবদ্ধ করে। বাম হাতের কমান্ডটি *.coverপাথগুলি দিয়ে পুনরাবৃত্তি করে এবং তাদের ডিরেক্টরিগুলির নাম মুদ্রণ করে।

পরীক্ষা রান:

$ find .   # let's see what we have here
.
./a
./a/b
./foo
./foo/bar
./foo/baz
./foo/baz/cover.jpg

$ diff  <(for x in */*/cover.jpg; do echo "$(dirname "$x")" ; done) <(printf "%s\n" */*)
0a1,2
> a/b
> foo/bar

আহা, a/bএবং foo/barডিরেক্টরিগুলির কোনও নেই cover.jpg

কিছু ভাঙা কোণার কেস রয়েছে যেমন ডিফল্টরূপে *নিজের কাছে প্রসারিত হয় যদি এটি কিছু না মেলে। এটি বাশের সাথে সম্বোধন করা যেতে পারে set -o nullglob


দেরিতে জবাবের জন্য দুঃখিত। এটি একটি আকর্ষণীয় ধারণা কিন্তু: কভার PNG এবং jpb হতে পারে এবং, না commচেয়ে ক্লিনার হতে diff?
অলি

comm -3 <(printf "%s\n" */*/cover* | sed -r 's/\/[^\/]+$//' | sort -u) <(printf "%s\n" */*)কোনওরকম ঝোঁক ছাড়াই কোনও বুদ্ধিমান সমঝোতার মতো মনে হচ্ছে diff। এটি অবশ্য আমার ডাবল ফাইন্ডের চেয়ে কিছুটা ধীর।
অলি

0
ls --color=never */*.txt | sed 's|/.*||' | sort -u -n > withtxt.txt
ls --color=never -d * | sort -u -n > all.txt
diff all.txt withtxt.txt

Txt ফাইল নেই এমন সমস্ত ডিরেক্টরি প্রদর্শন করবে।

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