এটি কীভাবে সঠিকভাবে করা যায়
প্রথমত, সর্বদা আপনার ভেরিয়েবলগুলি উদ্ধৃত করুন । আপনি যা করার চেষ্টা করছেন তা যদি আপনি সঠিকভাবে উদ্ধৃত করেন:
$ pwd
/home/terdon/foo/\e[92mM@r|< +'|'|_e|\|\|0rth [`-_-"]
$ ls
pullingATerdon
অবিচ্ছিন্নতার জন্য আপনি যে অদ্ভুত ফাইলের নামটি চয়ন করেছেন তা আমি রেখেছি ( যদিও আপনি কেন এটি বেছে নিয়েছেন তা আমার কোনও ধারণা নেই )।
এখন, আসুন pullingATerdon
একটি ভেরিয়েবলের পথ নির্ধারণ করুন এবং তারপরে ফাইলটি খোলার চেষ্টা করুন:
$ bacon="$(realpath pullingATerdon)"
$ echo "$bacon"
/home/terdon/foo/\e[92mM@r|< +'|'|_e|\|\|0rth [`-_-"]/pullingATerdon
$ ls $bacon
ls: cannot access '+'\''|'\''|_e|\|\|0rth': No such file or directory
ls: cannot access '[`-_-"]/pullingATerdon': No such file or directory
'/home/terdon/foo/\e[92mM@r|<':
প্রত্যাশার মতো ব্যর্থ হয়েছে। তবে, আমরা যদি এখন এটি সঠিকভাবে উদ্ধৃত করি:
$ ls -l "$bacon"
-rw-r--r-- 1 terdon terdon 0 Mar 14 23:15 '/home/terdon/foo/\e[92mM@r|< +'\''|'\''|_e|\|\|0rth [`-_-"]/pullingATerdon'
এটি প্রত্যাশার মতো কাজ করে। এবং হ্যাঁ, আপনি কোনও (যথাযথ) সম্পাদকটিতেও পথ খুলতে পারেন: emacs "$bacon"
ঠিকঠাক কাজ করবে। ঠিক আছে, তাই vim
এবং অন্য কিছু। আপনার সম্পাদকের পছন্দ দুর্ভাগ্যজনক হলেও প্রাসঙ্গিক নয়।
কেন আপনার ব্যর্থ
আপনার ক্ষেত্রে আসলে কী ঘটেছে তা চিহ্নিত করার একটি দ্রুত উপায় হ'ল ব্যবহার করা set -x
(এটি দিয়ে আবার বন্ধ করুন set +x
), যার ফলে শেলটি প্রতিটি কমান্ড মুদ্রণ করে এটি চালানোর আগে চালিত হয়। এর সাথে শেলের ডিবাগিং বার্তাগুলি চালু করুন set -x
:
$ set -x
$ /bin/ls $bacon
+ ls '/home/terdon/foo/\e[92mM@r|<' '+'\''|'\''|_e|\|\|0rth' '[`-_-"]/pullingATerdon'
ls: cannot access '+'\''|'\''|_e|\|\|0rth': No such file or directory
ls: cannot access '[`-_-"]/pullingATerdon': No such file or directory
'/home/terdon/foo/\e[92mM@r|<':
যে দেখায় আমাদের যে ls
তিনটি পৃথক আর্গুমেন্ট সহ চালানো হয়েছিল: '/home/terdon/foo/\e[92mM@r|<'
, '+'\''|'\''|_e|\|\|0rth'
এবং '[`-_-"]/pullingATerdon'
। শেলটি শব্দ বিভাজন এবং অবিরত স্ট্রিংগুলিতে গ্লোব সম্প্রসারণ সম্পাদন করে কারণ এটি ঘটে । এই ক্ষেত্রে, সমস্যাটি শব্দ বিভাজন, যেহেতু শেলটি পথের ফাঁকা স্থানগুলি দেখেছিল এবং প্রতিটি স্থান পৃথক যুক্ত স্ট্রিংকে পৃথক যুক্তি হিসাবে পড়বে।
mkdir
উদাহরণস্বরূপ কিছুটা ভিন্ন কিন্তু এটা এ কারণে যে তুমি আমাদের দেখাছে থেকে ত্রুটির বার্তা দ্বিতীয় কমান্ডের আবাহন। আমার ধারণা আপনি একবার চেষ্টা করে দেখেছেন এবং আপনার প্রশ্নের আউটপুট পেতে এটি দ্বিতীয়বার চালিয়েছেন। প্রথমবার যখন আপনি এটি চালাচ্ছিলেন, এটি দেখতে এইরকম লাগবে:
$ mkdir $(realpath pullingATerdon)
++ realpath pullingATerdon
+ mkdir '/home/terdon/foo/\e[92mM@r|<' '+'\''|'\''|_e|\|\|0rth' '[`-_-"]/pullingATerdon'
mkdir: cannot create directory ‘[`-_-"]/pullingATerdon’: No such file or directory
আবার, এটি শব্দ বিভাজনের কারণে একটি নয়, তিনটি ডিরেক্টরি তৈরি করার চেষ্টা করবে। প্রথমত, এটি ডিরেক্টরিটি তৈরি করেছে (সফলভাবে) /home/terdon/foo/\e[92mM@r|<
:
$ ls -l /home/terdon/foo/
total 8
drwxr-xr-x 2 terdon terdon 4096 Mar 15 00:20 '\e[92mM@r|<'
drwxr-xr-x 3 terdon terdon 4096 Mar 15 00:20 '\e[92mM@r|< +'\''|'\''|_e|\|\|0rth [`-_-"]'
এটির পরে, সফলভাবে, +'|'|_e|\|\|0rth
আপনার বর্তমান ডিরেক্টরিতে ডাকা একটি ডিরেক্টরি তৈরি করেছে :
$ ls -l
total 4
drwxr-xr-x 2 terdon terdon 4096 Mar 15 00:37 '+'\''|'\''|_e|\|\|0rth'
-rw-r--r-- 1 terdon terdon 0 Mar 15 00:36 pullingATerdon
এবং তারপরে, এটি ডিরেক্টরি তৈরি করার চেষ্টা করেছিল [`-_-"]/pullingATerdon
। এটি ব্যর্থ হয়েছে কারণ mkdir
, ডিফল্টরূপে, উপ-ডিরেক্টরি তৈরি করে না (এটি যদি আপনি এটি দিয়ে চালান তবে -p
):
$ mkdir baz/bar
mkdir: cannot create directory ‘baz/bar’: No such file or directory
যেহেতু আপনার অকেজো স্ট্রিংটিতে একটি রয়েছে /
, mkdir
এটি দুটি বিভাগের একটি পথ হিসাবে বিবেচনা করে শীর্ষস্থানীয়টি খুঁজতে চেষ্টা করেছিল এবং ব্যর্থ হয়েছিল।
এ কারণেই এটি ব্যর্থ হয়েছে, তবে যা ঘটেছে তা আরও জটিল। স্ট্রিং আপনাকে ব্যবহৃত আসলে একটি শেল উল্লিখিত glob, নির্দিষ্টভাবে একটি হল উল্লিখিত glob পরিসীমা , যা বর্তমান ডিরেক্টরী যার নাম 5 অক্ষরের এক সব ফাইল মিলে যায় `
, -
, _
বা "
। যেহেতু আপনার বর্তমান ডিরেক্টরিতে এ জাতীয় কোনও ফাইল নেই, তাই গ্লোব কোনও কিছুর সাথে মেলে না এবং যেমন ব্যাশের ডিফল্ট আচরণ, নিজেই ফিরে আসে:
$ echo "[\`-_-\"]/pullingATerdon" ## some escaping is needed here
+ echo '[`-_-"]/pullingATerdon' ## but it echoes the right thing
[`-_-"]/pullingATerdon ## and matches nothing, so returns itself.
স্পষ্ট করে বলার জন্য, আপনি যদি এমন কোনও গ্লোব দেন যা কোনও কিছুর সাথে মিলে না here
$ echo [p]* ## any filename starting with a p
pullingATerdon
$ echo "[p]*" ## the string "[p]*"
[p]*
আনকোটেড [p*]
ফাইলের নামের সাথে তাল মিলিয়ে প্রসারিত হয় (কেবলমাত্র একটি, এই ক্ষেত্রে) এবং এটিই পাস করা হয় echo
। তবুও অন্য কারণ আপনার সমস্ত বিষয় উদ্ধৃত করা উচিত।
অবশেষে, আপনি প্রদর্শিত প্রকৃত ত্রুটিটি হ'ল দ্বিতীয় বার আপনি কমান্ডটি চালিয়েছিলেন এবং এটি তৈরির চেষ্টা করার সময় প্রথম ধাপে এটি ব্যর্থ হয় /home/terdon/foo/\e[92mM@r|<
, কারণ পূর্ববর্তী অনুরোধটি ইতিমধ্যে ডিরেক্টরিটি তৈরি করেছিল।
আরও সাধারণভাবে, যখনই আপনি নিজেকে স্বেচ্ছাসেবী ফাইলের নাম নিয়ে কাজ করতে দেখেন, সর্বদা শেল গ্লোব ব্যবহার করুন। এই জাতীয় জিনিস:
for file in *; do command "$file"; done
এটি যে কোনও ফাইলের নামের জন্য কাজ করবে। এটি ধারণ করে কী ঘটে তা নয়। আমাদের উপরের উদাহরণে আপনি করতে পারতেন:
emacs /home/terdon/*92mM*/pullingATerdon
লক্ষ্য ফাইলটি অনন্যভাবে চিহ্নিত করে এমন কোনও গ্লোবই করবে। এইভাবে, আপনার বিশেষ চরিত্রগুলির সম্পর্কে চিন্তা করার দরকার নেই এবং কেবল শেলটি তাদের পরিচালনা করতে দেয়।
কিছু দরকারী তথ্যসূত্র:
আমি কীভাবে নতুন লাইনেস, স্পেস বা উভয় সমন্বিত ফাইলের নামগুলি নিরাপদে সন্ধান করতে এবং সুরক্ষিত করতে পারি? : দুর্দান্ত গ্রে ক্যাট এর উইকির অন্যতম FAQ।
বাশ / পসিক্স শেলের একটি পরিবর্তনশীল উদ্ধৃতি ভুলে যাওয়ার সুরক্ষা সম্পর্কিত বিষয়গুলি : এই উত্তরটির শুরুতে আমি একই পোস্টটি উল্লেখ করেছি। আপনার শেল ভেরিয়েবলগুলি সঠিকভাবে উদ্ধৃত করতে ব্যর্থ হলে ভুল হতে পারে এমন সমস্ত বিষয়ের একটি দুর্দান্ত এবং খুব বিশদ বিবরণ।
কেন আমার শেল স্ক্রিপ্টটি সাদা স্থান বা অন্যান্য বিশেষ চরিত্রগুলিতে শ্বাসরোধ করে? : শেলটিতে স্বেচ্ছাসেবক ফাইলের নামগুলি পরিচালনা করার বিষয়ে আপনি যা জানতে চেয়েছিলেন তা সবই।
কখন ডাবল-কোটিং দরকার? : উদ্ধৃতি এবং ভেরিয়েবল সম্পর্কে এবং বিশেষত, কয়েকটি ক্ষেত্রে যেখানে আপনার উদ্ধৃতি দেওয়ার দরকার নেই
vim "$bacon"