यह खोजने के साथ ग्लोबिंग के साथ हल करने के लिए बहुत अच्छा है।
$ 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
।