ম্যাকে, কমান্ডটি চলার আগেই ডিফল্ট zsh শেল যাতে ওয়াইল্ডকার্ড প্যাটার্নটি এক্সপ্যান্ড না করে, সেজন্য সেটিকে একক উদ্ধৃতিতে (সিঙ্গেল কোট) রাখুন। উদাহরণস্বরূপ, printf '%s\n' '*.csv' আর্গুমেন্ট হিসেবে হুবহু *.csv টেক্সটটি পাস করে। উদ্ধৃতিচিহ্নগুলো শেল দ্বারা অপসারিত হয়; অ্যাস্টেরিস্কটি প্রোগ্রাম পর্যন্ত পৌঁছায়। প্রোগ্রামটি নিজে প্যাটার্ন ব্যবহার করলে পরবর্তীতে সেটি ওই অ্যাস্টেরিস্কের অর্থ ব্যাখ্যা করতে পারে।
কমান্ড চলার আগে ওয়াইল্ডকার্ড কেন পরিবর্তিত হয়
টার্মিনালে আপনি কোনো কমান্ড দিলে শেল প্রোগ্রামটি শুরু করার আগেই তার আর্গুমেন্টগুলো প্রসেস করে। zsh-এ, কোটেশন ছাড়া থাকা একটি * ফাইলের নাম তৈরি (filename generation) শুরু করে দিতে পারে: শেল প্যাটার্নটির সাথে মিলে যাওয়া ফাইলের নামগুলো প্রতিস্থাপন করে দেয়। যদি কোনো মিল না থাকে, তাহলে zsh সাধারণত একটি এরর দেখায়, যদিও শেলের অপশন পরিবর্তন করে এই আচরণ বদলানো যায়। The zsh manual describes filename generation and its no-match behavior।
অ্যাপল zsh-কে টার্মিনালের ডিফল্ট শেল হিসেবে নির্ধারণ করেছে, যদিও অন্য শেল ব্যবহার করার জন্য ম্যাক কনফিগার করা সম্ভব। Apple’s Terminal guide explains the default and how to change it। নিচের সিঙ্গেল-কোট পদ্ধতিটি zsh এবং Bash-এর জন্য উপযুক্ত; আপনি যদি ভিন্ন কোনো শেল ব্যবহার করেন, তবে সেটির ম্যানুয়াল দেখে নিন, কারণ কোটেশনের নিয়মাবলী ভিন্ন হতে পারে।
হুবহু ওয়াইল্ডকার্ড পেতে সিঙ্গেল কোট ব্যবহার করুন
ওয়াইল্ডকার্ড প্যাটার্নের সাথে থাকা অন্য যেকোনো ক্যারেক্টার অক্ষুণ্ণ রেখে পুরো প্যাটার্নটিকে সিঙ্গেল কোট চিহ্নের মধ্যে লিখুন। যেমন:
printf '%s\n' '*.csv'
বর্তমান ডিরেক্টরিতে CSV ফাইল থাকুক বা না থাকুক, আউটপুট হবে হুবহু *.csv। printf প্যাটার্নটিকে একটি আর্গুমেন্ট হিসেবে গ্রহণ করে এবং তা প্রিন্ট করে; শেল অ্যাস্টেরিস্কটিকে এক্সপ্যান্ড করে না। কোটেশনগুলো শেলের সিনট্যাক্স, তাই সেগুলো আর্গুমেন্টে অন্তর্ভুক্ত থাকে না। অ্যাপলের শেল স্ক্রিপ্টিং গাইডে ব্যাখ্যা করা হয়েছে যে সিঙ্গেল কোট উদ্ধৃত লেখার ভেতরে শেল এক্সপ্যানশন নিষ্ক্রিয় করে। Apple: Flow Control, Expansion, and Parsing।
কোনো প্রোগ্রাম যখন নিজে কোনো প্যাটার্ন হ্যান্ডেল করতে চায়, তখন এটি বিশেষভাবে গুরুত্বপূর্ণ। উদাহরণস্বরূপ, macOS-এ find কমান্ড -name-এ দেওয়া প্যাটার্নটি ব্যবহার করে ফাইলের নামের মিল খুঁজে পেতে পারে:
find . -type f -name '*.log'
এখানে, শেল *.log-কে হুবহু find-এর কাছে পাস করে; তারপর find বর্তমান ডিরেক্টরির ভেতরের ফাইলগুলোর ক্ষেত্রে নিজস্ব ফাইলের নাম মেলানোর নিয়ম প্রয়োগ করে। কোটেশন ব্যবহারের ফলে find ব্যবহার করার আগেই শেল বর্তমান ডিরেক্টরির নামগুলো দিয়ে প্যাটার্নটিকে প্রতিস্থাপন করে ফেলতে পারে না। প্যাটার্নটির অর্থ নির্ভর করে গ্রহণকারী প্রোগ্রামের ওপর: শেলের কোটেশন শেলের এক্সপ্যানশন নিয়ন্ত্রণ করে, প্রোগ্রাম কীভাবে তার আর্গুমেন্টের অর্থ গ্রহণ করবে তা নয়।
কখন পরিবর্তে ব্যাকস্ল্যাশ ব্যবহার করবেন
ছোট প্যাটার্নের ক্ষেত্রে, কোটেশনের বাইরে থাকা কোনো নির্দিষ্ট ওয়াইল্ডকার্ডকে সুরক্ষিত করতে একটি ব্যাকস্ল্যাশ ব্যবহার করা যেতে পারে:
printf '%s\n' \*.csv
এটিও অ্যাস্টেরিস্কটিকে হুবহু পাস করে। যখন একটি প্যাটার্নে বেশ কয়েকটি বিশেষ ক্যারেক্টার, স্পেস বা ব্র্যাকেট থাকে, তখন প্রায়ই সিঙ্গেল কোট পড়া সহজ হয়। উদাহরণস্বরূপ, 'chapter [0-9]*.txt' ব্র্যাকেট ও ওয়াইল্ডকার্ডকে শেল কর্তৃক রূপান্তরিত হওয়া থেকে রক্ষা করে। অ্যাপল তাদের শেল স্ক্রিপ্টিং গাইডে ব্যাকস্ল্যাশ কোটিং এবং সিঙ্গেল-কোটের আচরণের বিবরণ দিয়েছে।
কোটেশন সংক্রান্ত সাধারণ ভুলত্রুটি
ডাবল কোট শেলের প্রতিটি ক্যারেক্টারকে নির্ভরযোগ্যভাবে সুরক্ষিত রাখতে পারে না। এগুলো zsh-এ ওয়াইল্ডকার্ডের বিস্তার রোধ করে ঠিকই, কিন্তু এখনও কিছু এক্সপ্যানশনের অনুমতি দেয়, যার মধ্যে $name-এর মতো ভ্যারিয়েবল এবং $(command)-এর মতো কমান্ড প্রতিস্থাপন অন্তর্ভুক্ত। যে প্যাটার্নটি হুবহু টাইপ করা রূপেই পাওয়া প্রয়োজন, সেটির ক্ষেত্রে সিঙ্গেল কোট ব্যবহার করুন, যদি না আর্গুমেন্টটির জন্য ওই ধরনের কোনো এক্সপ্যানশনের প্রয়োজন হয়।
সিঙ্গেল কোটেশনের ভেতরে থাকা কোনো টেক্সটে সাধারণ ক্যারেক্টার হিসেবে সিঙ্গেল কোট আসতে পারে না। প্যাটার্নটির নিজের মধ্যেই যদি কোনো অ্যাপোস্ট্রফি থাকে, তবে কোট করা অংশটি বন্ধ করুন, অন্য কোটেশন পদ্ধতি ব্যবহার করে অ্যাপোস্ট্রফিটি যোগ করুন এবং পুনরায় সিঙ্গেল কোট শুরু করুন; অ্যাপল তাদের গাইডে এই শেল কোটেশন কৌশলটি দেখিয়েছে। অস্বাভাবিক প্যাটার্নের ক্ষেত্রে, কমান্ডটি চালানোর আগে সতর্কতার সাথে হুবহু পরীক্ষা করে নিন।
এছাড়াও শেল এক্সপ্যানশন এবং গ্রহণকারী প্রোগ্রামের আচরণের মধ্যকার পার্থক্যটি বুঝতে হবে। *.log-কে কোটেশনে রাখলে প্রোগ্রামটি যে অ্যাস্টেরিস্ককে একটি সাধারণ ক্যারেক্টার হিসেবে বিবেচনা করতে বাধ্য হবে এমন নয়; এটি কেবল নিশ্চিত করে যে শেল এটিকে হুবহু পাস করেছে। find -name-এর মতো একটি ইউটিলিটি এটিকে একটি প্যাটার্ন হিসেবে ব্যাখ্যা করতে পারে, যেখানে অন্য কোনো কমান্ড এটিকে সাধারণ অক্ষর হিসেবে গ্রহণ করতে পারে। এই পার্থক্যটি গুরুত্বপূর্ণ হলে সেই কমান্ডের নিজস্ব ডকুমেন্টেশন দেখে নিন।
Return চাপার আগে একটি দ্রুত যাচাই
প্রোগ্রামটির কী গ্রহণ করা উচিত তা বিবেচনা করুন। যদি এর একটি ওয়াইল্ডকার্ড প্যাটার্নের প্রয়োজন হয়, তবে প্যাটার্নটিকে সিঙ্গেল কোটে রাখুন এবং নিশ্চিত করুন যে কমান্ডের অপশনগুলো প্যাটার্নটিকে উদ্দেশ্য অনুযায়ী ব্যাখ্যা করার জন্য সেট করা হয়েছে। প্রোগ্রামটি যদি একটি বাস্তব ফাইলের নাম পাওয়ার কথা থাকে, তবে যেখানে উপযুক্ত সেখানে শেল এক্সপ্যানশন সক্রিয় রাখুন, অথবা সরাসরি ফাইলের নামটি দিন। মূল বিষয় হলো, আপনি যখন চান প্রোগ্রামটি নিজে ওয়াইল্ডকার্ড ক্যারেক্টারগুলো গ্রহণ করুক, তখন শেলের সীমানাতেই কোটেশন ব্যবহার করতে হবে।
উৎসসমূহ
14 Expansion (zsh) — zsh.sourceforge.io
Change the default shell in Terminal on Mac — Apple Support
Flow Control, Expansion, and Parsing — Apple Developer