ইউনিক্স শেল শিখতে চাওয়ার একটি সাধারণ কারণ হলো ব্যাচ প্রসেসিং-এর শক্তি আনলক করা। আপনি যদি অনেক ফাইলের ওপর কাজের একটি সেট করতে চান, তবে সেটি করার একটি উপায় হলো একটি কমান্ড কনস্ট্রাক্ট করা যা সেই ফাইলগুলোর ওপর ইটারেট করে। প্রোগ্রামিং টার্মিনোলজিতে, এটিকে এক্সিকিউশন কন্ট্রোল বলা হয়, এবং এর সবচেয়ে সাধারণ উদাহরণ হলো for লুপ।
একটি for লুপ হলো একটি রেসিপি যা ডিটেইল করে আপনি আপনার কম্পিউটারকে কী কী একশন নিতে চান প্রতি ডেটা অবজেক্ট (যেমন একটি ফাইল) আপনি স্পেসিফাই করেছেন।
ক্লাসিক for লুপ
একটি সহজ লুপ ট্রাই করতে পারেন যা ফাইলগুলোর একটি সংগ্রহ বিশ্লেষণ করে। এটি আপন आपে একটি উপকারী লুপ নয়, কিন্তু এটি নিজের আপনাকে প্রমাণ করার একটি নিরাপদ উপায় যে আপনি একটি ডিরেক্টরির প্রতিটি ফাইলকে আলাদা আলাদা হ্যান্ডল করতে পারেন। প্রথমে একটি সিম্পল টেস্ট এনভায়রনমেন্ট তৈরি করুন একটি ডিরেক্টরি বানিয়ে এবং কিছু ফাইল কপি করে সেটাতে রাখুন। যেকোনো ফাইল चलेगा প্রাথমিকভাবে, لكن লেটার উদাহরণগুলো গ্রাফিক ফাইল (যেমন JPEG, PNG, বা সাদৃশ্য) চায়। আপনি ফোল্ডারটি তৈরি করতে এবং ফাইল কপি করতে ফাইল ম্যানেজার বা টার্মিনাল ব্যবহার করতে পারেন:
$ mkdir example
$ cp ~/Pictures/vacation/*.{png,jpg} example
আপনার নতুন ফোল্ডারে ডিরেক্টরি চেঞ্জ করুন, তারপর সেটার ফাইলগুলো লিস্ট করুন যাতে কনফার্ম করতে পারেন যে আপনার টেস্ট এনভায়রনমেন্ট আপনার আশা অনুযায়ী:
$ cd example $ ls -1 cat.jpg design_maori.png otago.jpg waterfall.png
প্রতিটি ফাইলকে আলাদা আলাদা লুপ করার সিনট্যাক্স হলো: একটি ভেরিয়েবল তৈরি করুন (f ফাইলের জন্য, উদাহরণস্বরূপ)। তারপর সেই ডেটা সেট ডিফাইন করুন যা আপনি ভেরিয়েবলকে সাইকেল করতে চান। এই কেসে, কারেন্ট ডিরেক্টরির সব ফাইল দিয়ে সাইকেল করুন * ওয়াইল্ডকার্ড ক্যারেক্টার ব্যবহার করে ( * ওয়াইল্ডকার্ড সবকিছু ম্যাচ করে)। তারপর এই ইন্ট্রোডাক্টরি ক্লজকে সেমিকোলন (;) দিয়ে টার্মিনেট করুন।
$ for f in * ;
আপনার পছন্দ অনুযায়ী, আপনি এখানে Return চাপতে পারেন। শেল লুপটি এক্সিকিউট করার চেষ্টা করবে না যতক্ষণ না সেটি সিনট্যাক্টিক্যালি কমপ্লিট হয়।
পরবর্তী, আপনি লুপের প্রতিটি ইটারেশনে কী হব তা ডিফাইন করুন। সিম্পলিসিটির জন্য, file কমান্ড ব্যবহার করুন প্রতিটি ফাইলের সম্পর্কে কিছু ডেটা পেতে, যা f ভেরিয়েবল দ্বারা প্রতিনিধিত্ব করা হচ্ছে (পERO ডলার সাইন $ দিয়ে প্রিপেন্ড করা হয়েছে যাতে শেল ভেরিয়েবলের মান বদলে দিয়ে দেয় যেকোনো সময় ভেরিয়েবলটি ধারণ করছে):
do file $f ;
আরেকটি সেমিকোলন দিয়ে ক্লজ টার্মিনেট করুন এবং লুপ বন্ধ করুন:
done
Return চাপুন শেলকে কারেন্ট ডিরেক্টরির সবকিছু দিয়ে সাইকেল করতে। for লুপ প্রতিটি ফাইলকে একে একে ভেরিয়েবল f-এ অ্যাসাইন করে এবং আপনার কমান্ড রান করে:
$ for f in * ; do > file $f ; > done cat.jpg: JPEG image data, EXIF standard 2.2 design_maori.png: PNG image data, 4608 x 2592, 8-bit/color RGB, non-interlaced otago.jpg: JPEG image data, EXIF standard 2.2 waterfall.png: PNG image data, 4608 x 2592, 8-bit/color RGB, non-interlaced
আপনি এটিকে এইভাবেও লিখতে পারেন:
$ for f in *; do file $f; done cat.jpg: JPEG image data, EXIF standard 2.2 design_maori.png: PNG image data, 4608 x 2592, 8-bit/color RGB, non-interlaced otago.jpg: JPEG image data, EXIF standard 2.2 waterfall.png: PNG image data, 4608 x 2592, 8-bit/color RGB, non-interlaced
মাল্টি-লাইন এবং সিঙ্গল-লাইন ফরম্যাট দুটোই আপনার শেলের কাছে একই এবং একই ফলাফল দেয়।
একটি ব্যবহারিক উদাহরণ
এখানে একটি ব্যবহারিক উদাহরণ কীভাবে একটি লুপ দৈনন্দিন কম্পিউটিং-এ উপকারী হতে পারে। অনুমান করুন আপনার একটি ভ্যাকেশন ফটো সংগ্রহ আছে যা আপনি বন্ধুদের পাঠাতে চান। আপনার ফটো ফাইলগুলো খুব বড়, তাই ইমেইল করার জন্য বড় এবং ফটো শেয়ারিং সার্ভিসে আপলোড করার জন্য অসুবিধাজনক। আপনি আপনার ফটোর ছোট ওয়েব-ভার্সন তৈরি করতে চান, কিন্তু আপনার ১০০টি ফটো আছে এবং প্রতিটি ফটো একে একে রিসাইজ করার জন্য সময় খরচ করতে চান না।
প্রথমে, ImageMagick কমান্ড ইনস্টল করুন আপনার প্যাকেজ ম্যানেজার ব্যবহার করে লিনাক্স, BSD, বা Mac-এ। উদাহরণস্বরূপ, ফেডোরা এবং RHEL-এ:
$ sudo dnf install ImageMagick
Ubuntu বা Debian-এ:
$ sudo apt install ImageMagick
BSD-এ, ports বা pkgsrc ব্যবহার করুন। Mac-এ, Homebrew বা MacPorts ব্যবহার করুন।
ImageMagick ইনস্টল হলে, আপনার पास ফটোতে অপারেশন করার জন্য কিছু নতুন কমান্ড হবে।
আপনি যে ফাইলগুলো তৈরি করতে যাচ্ছেন সেগুলোর জন্য একটি ডেস্টিনেশন ডিরেক্টরি তৈরি করুন:
$ mkdir tmp
প্রতিটি ফটোকে এর মূল আকারের ৩৩% করে রিসাইজ করতে এই লুপটি ট্রাই করুন:
$ for f in * ; do convert $f -scale 33% tmp/$f ; done
তারপর tmp ফোল্ডারে দেখুন আপনার স্কেল করা ফটোগুলো।
আপনি একটি লুপের ভিতরে যেকোনো সংখ্যক কমান্ড ব্যবহার করতে পারেন, তাই আপনি যদি একটি ব্যাচ ফাইলের ওপর জটিল অ্যাকশন করতে চান, তবে আপনার পুরো ওয়ার্কফ্লো for লুপের do এবং done স্টেটমেন্টের মাঝপথে রাখতে পারেন। উদাহরণস্বরূপ, অনুমান করুন আপনি প্রতিটি প্রসেস করা ফটো সরাসরি আপনার ওয়েব হোস্টের একটি শেয়ার্ড ফটো ডিরেক্টরিতে কপি করতে চান এবং আপনার লোকাল সিস্টেম থেকে ফাইলটি রিমুভ করতে চান:
$ for f in * ; do convert $f -scale 33% tmp/$f scp -i seth_web tmp/$f seth@example.com:~/public_html trash tmp/$f ; done
for লুপ দ্বারা প্রসেস করা প্রতিটি ফাইলের জন্য, আপনার কম্পিউটার স্বয়ংক্রিয়ভাবে তিনটি কমান্ড রান করে। এর মানে আপনি যদি মাত্র ১০টি ফটো এইভাবে প্রসেস করেন, আপনি ৩০টি কমান্ড এবং সম্ভবত ততটাই মিনিট বাঁচাতে পারেন।
আপনার লুপ সীমাবদ্ধ করা
একটি লুপ সবসময় সব ফাইল দেখতে বাধ্য নয়। আপনি আপনার উদাহরণ ডিরেক্টরির শুধু JPEG ফাইলগুলো প্রসেস করতে চাইতে পারেন:
$ for f in *.jpg ; do convert $f -scale 33% tmp/$f ; done $ ls -m tmp cat.jpg, otago.jpg
অথবা, ফাইল প্রসেস করার বদলে, আপনি একটি নির্দিষ্ট সংখ্যক বার একটি অ্যাকশন রিপিট করতে চাইতে পারেন। একটি for লুপের ভেরিয়েবল ডিফাইন করা হয় আপনি যেই ডেটা দেন তার দ্বারা, তাই আপনি একটি লুপ তৈরি করতে পারেন যা ফাইল ছাড়া নাম্বার দিয়ে ইটারেট করে:
$ for n in {0..4}; do echo $n ; done
0
1
2
3
4
আরও লুপিং
আপনি এখন আপনার নিজের লুপ তৈরি করার জন্য পর্যাপ্ত জানেন। আপনি লুপিং-এ কমফার্টেবল না হওয়া পর্যন্ত, আপনি যেই ফাইলগুলো প্রসেস করতে চান তাদের কপি থেকে ব্যবহার করুন এবং, যতটা সম্ভব, বিল্ট-ইন সেফগার্ড সহ কমান্ড ব্যবহার করুন যাতে আপনি আপনার ডেটা ক্লবার করে অপরিবর্তনীয় ভুল না করেন, যেমন অকস্মাত পুরো ডিরেক্টরির ফাইলগুলোর একই নামে রিনেম করা, প্রতিটি অন্যকে ওভাররাইট করা।
অ্যাডভান্সড for লুপ টপিক্সের জন্য, পড়তে থাকুন।
সব শেল বাশ নয়
for কিওয়ার্ড বাশ শেলে বিল্ট-ইন। অনেক সাদৃশ্য শেল একই কিওয়ার্ড এবং সিনট্যাক্স ব্যবহার করে, কিন্তু কিছু শেল, যেমন tcsh, ভিন্ন কিওয়ার্ড ব্যবহার করে, যেমন foreach।
tcsh-এ, সিনট্যাক্স স্পিরিটে সাদৃশ্য কিন্তু বাশ চেয়ে স্ট্রিক্ট। নিচের কোড স্যাম্পলে, লাইন ২ এবং ৩-এ foreach? স্ট্রিং টাইপ করবেন না। এটি একটি সেকেন্ডারি প্রম্পট যা আপনাকে সতর্ক করে যে আপনি এখনও আপনার লুপ বিল্ড করার প্রক্রিয়ায় আছেন।
$ foreach f (*) foreach? file $f foreach? end cat.jpg: JPEG image data, EXIF standard 2.2 design_maori.png: PNG image data, 4608 x 2592, 8-bit/color RGB, non-interlaced otago.jpg: JPEG image data, EXIF standard 2.2 waterfall.png: PNG image data, 4608 x 2592, 8-bit/color RGB, non-interlaced
tcsh-এ, foreach এবং end উভয়ই আলাদা লাইনে থাকতে হবে, তাই আপনি বাশ এবং সাদৃশ্য শেলের মত এক লাইনে for লুপ তৈরি করতে পারবেন না।
find কমান্ড দিয়ে for লুপ
তত্ত্বাবধানে, আপনি একটি শেল খুঁজে পেতে পারেন যা for লুপ ফাংশন প্রদান করে না, অথবা আপনি শুধু একটি আলাদা কমান্ড পছন্দ করতে পারেন যেটে আরও ফিচার আছে।
find কমান্ড for লুপের ফাংশন্যালিটি ইমপ্লিমেন্ট করার আরেকটি উপায়, কারণ এটি আপনার লুপে কোন ফাইলগুলো ইনক্লুড করতে হবে সেটি ডিফাইন করার অনেক উপায় এবং প্যারালlel প্রসেসিং-এর অপশন দিয়ে থাকে।
find কমান্ড আপনাকে আপনার হার্ড ড্রাইভে ফাইল খুঁজে বের করতে সাহায্য করার জন্য। এর সিনট্যাক্স সিম্পল: আপনি যে লোকেশনটি সার্চ করতে চান তার পথ দিন, এবং find সব ফাইল এবং ডিরেক্টরি খুঁজে বের করবে:
$ find . . ./cat.jpg ./design_maori.png ./otago.jpg ./waterfall.png
আপনি কিছু অংশ নামের যোগ করে সার্চ ফলাফল ফিল্টার করতে পারেন:
$ find . -name "*jpg" ./cat.jpg ./otago.jpg
find-এর চমৎকার দিক হলো এটি যে প্রতিটি ফাইল খুঁজে পায়, সেটিকে -exec ফ্ল্যাগ ব্যবহার করে একটি লুপে ফিড করা যায়। উদাহরণস্বরূপ, আপনার উদাহরণ ডিরেক্টরির শুধু PNG ফটোগুলো স্কেল ডাউন করতে:
$ find . -name "*png" -exec convert {} -scale 33% tmp/{} \;
$ ls -m tmp
design_maori.png, waterfall.png
-exec ক্লজে, ব্র্যাকেট ক্যারেক্টার {} দাঁড়িয়ে থাকে যে আইটেমটি find প্রসেস করছে (অর্থাৎ, PNG-এ শেষ হওয়া যেকোনো ফাইল যা লোকেট করা হয়েছে, একে একে)। -exec ক্লজকে অবশ্যই সেমিকোলন দিয়ে টার্মিনেট করতে হবে, কিন্তু বাশ সাধারণত সেমিকোলন নিজের জন্য ব্যবহার করতে চায়। আপনি ব্যাকস্ল্যাশ (\;) দিয়ে সেমিকোলনটি "এস্কেপ" করেন যাতে find সেটিকে তার টার্মিনেটিং ক্যারেক্টার হিসেবে বিবেচনা করে।
find কমান্ড তার কাজে খুব দক্ষ, এবং কখনো কখনো এটি খুব বেশি দক্ষ হয়। উদাহরণস্বরূপ, আপনি যদি অন্য একটি ফটো প্রসেসের জন্য PNG ফাইল খুঁজতে এটিকে পুনরায় ব্যবহার করেন, তবে আপনি কিছু এরর পাবেন:
$ find . -name "*png" -exec convert {} -flip -flop tmp/{} \;
convert: unable to open image `tmp/./tmp/design_maori.png':
No such file or directory @ error/blob.c/OpenBlob/2643.
...
লাগছে find সকল PNG ফাইল লোকেট করেছে—না শুধু আপনার কারেন্ট ডিরেক্টরির (.) বরং সেগুলোও যেগুলো আপনি আগে প্রসেস করে tmp সাবডিরেক্টরিতে রাখেছিলেন। কিছু কেসে, আপনি চাইতে পারেন find কারেন্ট ডিরেক্টরি প্লাস তার ভিতরের সকল ডিরেক্টরি (এবং সেগুলোর ভিতরের সকল ডিরেক্টরি) সার্চ করবে। এটি জটিল ফাইল স্ট্রাকচার (যেমন muzik আর্টিস্টের ডিরেক্টরি যাতে অ্যালবামের ডিরেক্টরি থাকে যাতে মিউজিক ফাইল থাকে) এ খুব শক্তিশালী রিকার্সিভ প্রসেসিং টুল হতে পারে, কিন্তু আপনি -maxdepth অপশন দিয়ে সীমাবদ্ধ করতে পারেন।
কারেন্ট ডিরেক্টরিতে শুধু PNG ফাইল খুঁজতে (সাবডিরেক্টরি বাদে):
$ find . -maxdepth 1 -name "*png"
কারেন্ট ডিরেক্টরি প্লাস একটি অ্যাডিশনাল লেভেল সাবডিরেক্টরিতে ফাইল খুঁজে এবং প্রসেস করতে, ম্যাক্স ডেপথ ১ বাড়ান:
$ find . -maxdepth 2 -name "*png"
তার ডিফল্ট হলো সকল সাবডিরেক্টরিতে ডিসেন্ড করা।
লুপিং ফান অ্যান্ড প্রফিটের জন্য
আপনি যত বেশি লুপ ব্যবহার করবেন, তত বেশি সময় ও পরিশ্রম বাঁচাবেন, এবং তত বড় টাস্ক হ্যান্ডল করতে পারবেন। আপনি শুধু একজন ব্যবহারকারী, কিন্তু একটি ভালো চিন্তা করা লুপ দিয়ে আপনি আপনার কম্পিউটারকে কঠিন কাজ করাতে পারেন।
আপনি লুপিংকে যেকোনো অন্য কমান্ডের মতই বিবেচনা করতে পারেন, এটিকে হাতের মুঠোয় রাখুন যখন আপনাকে একটি বা দুটি অ্যাকশন অনেক ফাইলে রিপিট করতে হবে। যাইহোক, এটি সিরিয়াস প্রোগ্রামিং-এ একটি লেজিটিমেট গেটওয়ে, তাই আপনি যদি যেকোনো সংখ্যক ফাইলে একটি জটিল টাস্ক সম্পন্ন করতে চান, আপনার দিন থেকে কিছু মুহূর্ত বের করুন আপনার ওয়ার্কফ্লো প্ল্যান করতে। আপনি যদি এক ফাইলে আপনার লক্ষ্য অর্জন করতে পারেন, তবে সেই রিপিটেবল প্রসেসকে একটি for লুপে মোড়ানো তুলনামূলকভাবে সহজ, এবং একমাত্র "প্রোগ্রামিং" যা দরকার হলো ভেরিয়েবল কীভাবে কাজ করে সেটি বুঝতে এবং অপ্রসেসড ফাইলগুলো প্রসেসড ফাইলগুলো থেকে আলাদা রাখার জন্য পর্যাপ্ত সংগঠন। একটু প্র্যাক্টিস দিয়ে, আপনি একটি লিনাক্স ব্যবহারকারী থেকে একটি লিনাক্স ব্যবহারকারী হয়ে উঠতে পারেন যিনি জানেন কীভাবে একটি লুপ লিখতে হয়, তাই বের হোন এবং আপনার কম্পিউটারকে আপনার জন্য কাজ করান!