چرا گنو/لینوکس رو دوست دارم: اضافه کردن اسم فایل به تبلچرهای گیتار

دوستم یک مشکل داره و می دونه شکل مشکل چیزی است از یک کار تکراری که احتمالا در دنیای قشنگ لینوکس می شه براش راه حل های جالب پیدا کرد. صورت مساله اینه:

من تعداد زیادی فایل تبلچر (شیوه اجرای آهنگ) گیتار دارم که اسم خواننده بالاشون نوشته نشده. در نتیجه من نمی تونم سریع توی ذهنم بیارم که آهنگ چه شکلی است. مثلا وقتی بالای آهنگ نوشته شده «عسل» کمک بسیار بزرگی است اگر Ebi رو هم بالاش ببینم. این Ebi اسم فایل است پس من یکسری فایل عکس دارم که می خوام اسم فایل رو روی عکس فایل اضافه کنم

بله! لینوکس که ترکیبی از ابزارهای قدرتمند است، راه حلی عالی داره. اما یک برنامه نویس خوب همیشه اول مسائل رو در ساده ترین حالت حل می کنه و بعد مساله رو پیچیده می کنه. فرض کنیم اصولا فقط یک عکس داریم که می خوایم روش بنویسیم My Happy Text. اسم فایل هم هست Bijan Mortazavi 006. اگر بتونیم این مساله رو حل کنیم، یک قدم جلو افتادیم. در اصل من دارم مساله رو به سه بخش تقسیم می کنم:

1- اضافه کردن یک متن دلخواه به یک عکس
2- در آوردن اسم یک فایل
3- ترکیب کردن دو قدم قبلی برای هر چند تا فایل که داشتیم

قدم اول: نوشتن روی فایل

ساده است. بسته Image Magick ابزاری داره به اسم convert که می تونه تقریبا هر کاری با یک تصویر بکنه! مثلا این تصویر:

Ebi 005

با دستور

$ convert Ebi\ 005.JPG -pointsize 43 -background Khaki label:'My Happy Text' +swap -gravity Center -append out.jpg

تبدیل می شه به:

out

جذاب نیست؟ بخصوص که روی تصویر چیزی ننوشتیم بلکه بالاش کمی تصویر اضافه کردیم! حالا می ریم سراغ قدم دوم.

قدم دوم: درآوردن فهرست فایلها

من احتیاج دارم اسم فایل ها رو بگیرم. اولش که ساده است؛ به لینوکس می گم همه فایل هایی که تهشون JPG هست رو بهم بده:

$ find . -name "*JPG" 
./Bijan Mortazavi 005.JPG
./Ebi 015.JPG
./Ebi 018.JPG
./Ebi 016.JPG
./Darush 007.JPG

بعد کافیه بگم اون /. اول رو حذف کنه:

a$ find . -name "*JPG" | sed "s/\.\///"
Bijan Mortazavi 005.JPG
Ebi 015.JPG
Ebi 018.JPG
Ebi 016.JPG
Darush 007.JPG

و چیز دیگه که بهش احتیاج نداریم اون JPG. آخر است:

$ find . -name "*JPG" | sed "s/\.\///" | sed "s/\.JPG//"
Bijan Mortazavi 005
Ebi 015
Ebi 018
Ebi 016
Darush 007

و قدم دوم هم تموم می شه!

قدم سوم: چسبوندن قدم های قبلی

اینجا گزینه ها خیلی زیادن. بریم جلو ببینیم چی می شه. مثلا من می تونم با دستور xargs ورودی قدم دوم رو استفاده کنم. اصل صفرم برنامه نویسی جادی رو یادتونه دیگه؟ «برنامه پیچیده ای که کار می کنه، برنامه ساده ای بوده که کار می کرده» پس بذارین در ساده ترین حالت، هر کدوم از خطوط ورودی رو بدیم به یک دستور اکو:

$ find . -name "*JPG" | sed "s/\.\///" | sed "s/\.JPG//" \
    | xargs -L1 -I THIS echo my command will work on \"THIS\" happily 
my command will work on Bijan Mortazavi 005 happily
my command will work on Ebi 015 happily
my command will work on Ebi 018 happily
my command will work on Ebi 016 happily
my command will work on Darush 007 happily

عالی! ما قهرمانیم. الان ورودی قدم دوم رو خط به خط دادیم به دستور اکو. (سوییچ I می گه این خط ورودی باید کجای دستور قرار بگیره). بذارین یک ضرب سعی کنیم اصل برنامه رو اجرا کنیم و خروجی رو بریزیم توی دایرکتوری out و البته قبلش طبق همون اصل اول برنامه نویسی جادی، با گذاشتن یک echo جلوی دستوری که ساختیم یک تست هم می گیریم:

$ find . -name "*JPG" | sed "s/\.\///" | sed "s/\.JPG//" | xargs -L1 -I THIS echo convert \"THIS.JPG\" -pointsize 43 -background Khaki label:\'THIS\' +swap -gravity Center -append \"out/THIS.jpg\"
convert "Bijan Mortazavi 005.JPG" -pointsize 43 -background Khaki label:'Bijan Mortazavi 005' +swap -gravity Center -append "out/Bijan Mortazavi 005.jpg"
convert "Ebi 015.JPG" -pointsize 43 -background Khaki label:'Ebi 015' +swap -gravity Center -append "out/Ebi 015.jpg"
convert "Ebi 018.JPG" -pointsize 43 -background Khaki label:'Ebi 018' +swap -gravity Center -append "out/Ebi 018.jpg"
convert "Ebi 016.JPG" -pointsize 43 -background Khaki label:'Ebi 016' +swap -gravity Center -append "out/Ebi 016.jpg"
convert "Darush 007.JPG" -pointsize 43 -background Khaki label:'Darush 007' +swap -gravity Center -append "out/Darush 007.jpg"

بله ظاهرا که همه چیز عالیه. بزن بریم! اکو رو حذف می کنم ولی با اینکه دستورهای بالا درست هستن، به دلیلی که نمی دونم چیه دستورات درست اجرا نمی شن. پس کارم رو راحت می کنم:

$ find . -name "*JPG" | sed "s/\.\///" | sed "s/\.JPG//" | xargs -L1 -I THIS echo convert \"THIS.JPG\" -pointsize 43 -background Khaki label:\'THIS\' +swap -gravity Center -append \"out/THIS.jpg\" > commands.sh
$ sh commands.sh 
$ ls out/
Bijan Mortazavi 001.jpg  Bijan Mortazavi 005.jpg  Darush 003.jpg  Darush 007.jpg  Darush 011.jpg   Delkash 003.jpg  Ebi 004.jpg  Ebi 008.jpg  Ebi 012.jpg  Ebi 016.jpg
Bijan Mortazavi 002.jpg  Bijan Mortazavi 006.jpg  Darush 004.jpg  Darush 008.jpg  Darush 012.jpg   Ebi 001.jpg      Ebi 005.jpg  Ebi 009.jpg  Ebi 013.jpg  Ebi 017.jpg
Bijan Mortazavi 003.jpg  Darush 001.jpg           Darush 005.jpg  Darush 009.jpg  Delkash 001.jpg  Ebi 002.jpg      Ebi 006.jpg  Ebi 010.jpg  Ebi 014.jpg  Ebi 018.jpg
Bijan Mortazavi 004.jpg  Darush 002.jpg           Darush 006.jpg  Darush 010.jpg  Delkash 002.jpg  Ebi 003.jpg      Ebi 007.jpg  Ebi 011.jpg  Ebi 015.jpg  Ebi 019.jpg

بله. دستوراتی که درست کرده بودم رو می ریزم توی یک فایل و بعد فایل رو اجرا می کنم و می بینیم که دایرکتوری out پر شده از فایل هایی که لازم بود این بلا سرشون بیاد. مثلا:

www.guitarestan.com

حالا می تونیم این کدها رو بدیم به دوستمون که روی سیستم خودش روی چند صد تبلچر دیگه اجرا کنه و این می شه یک فعالیت شاد و خوشحال که هم باعث می شه مهارتهای لینوکسی مون بالا بره، هم بهمون خوش بگذره هم مشکل یک دوستمون حل بشه.