কেন "কোন" ব্যবহার করবেন না? তাহলে কী ব্যবহার করবেন?


328

যখন একটি এক্সিকিউটেবল পাথ খুঁজছেন বা পরীক্ষণ আপনি একটি ইউনিক্স শেল কমান্ড নাম লিখুন কি হবে, বিভিন্ন ইউটিলিটি একটি আধিক্য (এর which, type, command, whence, where, whereis, whatis, hash, ইত্যাদি)।

আমরা প্রায়শই শুনি যা whichএড়ানো উচিত। কেন? পরিবর্তে আমাদের কী ব্যবহার করা উচিত?


3
আমি মনে করি ব্যবহারের বিরুদ্ধে বেশিরভাগ যুক্তি whichএকটি ইন্টারেক্টিভ শেল প্রসঙ্গে ধরে নিচ্ছেন। এই প্রশ্নটি ট্যাগ / বহনযোগ্যতা। তাই আমি "কি পরিবর্তে ব্যবহার করার জন্য যেমন এই প্রেক্ষাপটে প্রশ্ন ব্যাখ্যা whichএকটি প্রদত্ত নামের প্রথম এক্সিকিউটেবল এটি $PATH"। whichএলিয়াস, বিল্টিন এবং ফাংশনগুলির সাথে চুক্তির বিরুদ্ধে বেশিরভাগ উত্তর এবং কারণগুলি , যা বেশিরভাগ বাস্তব-বিশ্বের পোর্টেবল শেল স্ক্রিপ্টগুলিতে কেবল একাডেমিক আগ্রহ interest শেল স্ক্রিপ্ট চালানোর সময় স্থানীয়ভাবে সংজ্ঞায়িত উপাধি উত্তরাধিকার সূত্রে প্রাপ্ত হয় না (যদি আপনি এটির উত্স না করেন .)
ম্যাটবিয়ানকো 21'14

5
@ ম্যাটবিয়ানকো, হ্যাঁ, csh(এবং whichএখনও cshবেশিরভাগ বাণিজ্যিক ইউনিয়নে একটি স্ক্রিপ্ট) ~/.cshrcঅ ইন্টারঅ্যাক্টিভ হলে পড়তে পারে । এজন্য আপনি সিএস স্ক্রিপ্টগুলি সাধারণত শুরু করে দেখবেন #! /bin/csh -fwhichএটি আপনাকে এ্যালিয়াস দেওয়ার উদ্দেশ্যে নয় , কারণ এটি (ইন্টারেক্টিভ) ব্যবহারকারীদের জন্য একটি সরঞ্জাম হিসাবে বোঝানো হয়েছে csh। পসিক্স শেল ব্যবহারকারীদের আছে command -v
স্টাফেন চেজেলাস

@ রূডিমেয়ার, তারপরে উত্তরটি সর্বদা থাকবে যদি না আপনার শেলটি না থাকে (t)csh(বা যদি এটি আপনাকে সঠিক ফলাফল না দেয় তবে আপনার আপত্তি নেই), ব্যবহার করুন typeবা command -vপরিবর্তে । উত্তর দেখুন কেন
স্টাফেন চেজেলাস

1
@ রূডিমেয়ার, ( stat $(which ls)বেশ কয়েকটি কারণে ভুল (নিখোঁজ --, নিখোঁজ উদ্ধৃতি), কেবল ব্যবহারের জন্য নয় which)) আপনি ব্যবহার করবেন stat -- "$(command -v ls)"। এটি ধরে নেওয়া lsহ'ল প্রকৃতপক্ষে ফাইল সিস্টেমে পাওয়া একটি কমান্ড (আপনার শেলের একটি অন্তর্নির্মিত নন, বা ওরফে ফাংশন নয়)। whichআপনাকে ভুল পথ দিতে পারে (আপনার প্রবেশের শেলটি যে পথটি প্রবেশ করানো হবে তা নয় ls) বা অন্য কোনও শেলের কনফিগারেশনের সংজ্ঞা অনুসারে আপনাকে একটি উপন্যাস দেয় ...
স্টাফেন চ্যাজেলাস

1
@ রূডিমেয়ার, আবারও অনেকগুলি শর্ত রয়েছে যার অধীনে অনেকগুলি whichবাস্তবায়ন আপনাকে এমনকি এমন একটি শর্তও দেয় না lsযেটি আপনার শেলটিতে $PATHযা কিছু চাইতে lsপারে তা নির্বিশেষে) look sh -c 'command -v ls', বা zsh -c 'rpm -q --whatprovides =ls'আপনাকে সঠিক উত্তর দেওয়ার সম্ভাবনা বেশি। এখানে মূল বিষয়টি whichহ'ল এটি একটি ভাঙা heritageতিহ্য csh
স্টাফেন চেজেলাস

উত্তর:


365

আপনি কখনই ভাবেন নি যে এটি সম্পর্কে জানতে চাইবেন না এমন সমস্ত এখানে:

সারাংশ

বোর্নের মতো শেল স্ক্রিপ্টে এক্সিকিউটেবলের পাথের নাম পাওয়ার জন্য (কয়েকটি ক্যাভেট রয়েছে; নীচে দেখুন):

ls=$(command -v ls)

প্রদত্ত আদেশটি উপস্থিত রয়েছে কিনা তা জানতে:

if command -v given-command > /dev/null 2>&1; then
  echo given-command is available
else
  echo given-command is not available
fi

একটি ইন্টারেক্টিভ বোর্নের মতো শেলের প্রম্পটে:

type ls

whichকমান্ড সি-শেল থেকে একটি ভাঙা ঐতিহ্য রয়েছে এবং বোর্ন মত শাঁস একা ছেড়ে দেওয়া হয়।

ব্যবহারের ক্ষেত্রে

কোনও স্ক্রিপ্টের অংশ হিসাবে সেই তথ্যটি অনুসন্ধান করার বা শেল প্রম্পটে ইন্টারেক্টিভভাবে পার্থক্য রয়েছে।

শেল প্রম্পটে, সাধারণ ব্যবহারের কেসটি হ'ল: এই আদেশটি অদ্ভুত আচরণ করে, আমি কি সঠিকটি ব্যবহার করছি? টাইপ করলে ঠিক কী ঘটেছিল mycmd? আমি কি এটি আরও তাকান করতে পারি?

সেক্ষেত্রে আপনি জানতে চাইবেন যে আপনি কমান্ডটি আসলে কমান্ডটি না দিয়েই কমান্ডটি চাওয়ার সময় আপনার শেলটি কী করে।

শেল স্ক্রিপ্টগুলিতে এটি বেশ আলাদা হতে থাকে। শেল স্ক্রিপ্টে আপনি জানতে চান যে আপনি যেখানে করতে চান তা যদি চালানো হয় তবে কোথায় বা কোন কমান্ড কী তা জানতে চাওয়ার কোনও কারণ নেই। সাধারণত, আপনি যা জানতে চান সেটি এক্সিকিউটেবলের পথ, সুতরাং আপনি এ থেকে আরও তথ্য পেতে পারেন (এর সাথে সম্পর্কিত অন্য কোনও ফাইলের পাথের মতো, বা সেই পথে এক্সিকিউটেবল ফাইলের বিষয়বস্তু থেকে তথ্য পড়তে পারেন)।

ইন্টারেক্টিভ আপনার সম্পর্কে জানতে চাইতে পারেন সবmy-cmd কমান্ড সিস্টেমে উপলব্ধ, স্ক্রিপ্ট-এ, খুব কমই তাই।

উপলভ্য বেশিরভাগ সরঞ্জাম (যেমন প্রায়ই হয়) ইন্টারেক্টিভভাবে ব্যবহারের জন্য ডিজাইন করা হয়েছে।

ইতিহাস

ইতিহাসের একটি বিট আগে।

Un০ এর দশকের শেষভাগ পর্যন্ত প্রাথমিক ইউনিক্স শেলগুলির কোনও ফাংশন বা উপকরণ ছিল না। এক্সিকিউটেবলের মধ্যে কেবল theতিহ্যবাহী চেহারা $PATHcsh1978 চারপাশের চালু alias লেখা (যদিও cshপ্রথম মুক্তি মধ্যে 2BSDএকটি প্রক্রিয়াকরণ, মে 1979 সালে), এবং এছাড়াও .cshrcশেল কাস্টমাইজ করতে ব্যবহারকারীদের জন্য (প্রতি শেল, যেমন cshলেখা আছে .cshrc, এমনকি যখন না ইন্টারেক্টিভ স্ক্রিপ্ট মত)।

বোর্ন শেলটি ১৯৯৯ এর প্রথমদিকে ইউনিক্স ভি in এ প্রথম প্রকাশিত হওয়ার সময়, ফাংশন সমর্থনটি কেবলমাত্র অনেক পরে যুক্ত হয়েছিল (1984 সালে এসভিআর 2 তে) এবং যাইহোক, এতে কখনও কোনও rcফাইল ছিল না (এটি .profileআপনার পরিবেশকে কনফিগার করতে হবে, প্রতি সেলে শেল নয় )।

csh বোর্ন শেলটির চেয়ে অনেক বেশি জনপ্রিয় হয়ে উঠেছে (যদিও এটি বোর্ন শেলের তুলনায় অত্যন্ত খারাপ সিনট্যাক্স ছিল) এটি ইন্টারেক্টিভ ব্যবহারের জন্য আরও অনেক সুবিধাজনক এবং চমৎকার বৈশিষ্ট্য যুক্ত করছিল।

ইন 3BSD(1980), একটি whichcsh শেল স্ক্রিপ্ট জন্য যোগ করা হয়েছিল cshব্যবহারকারীদের একটি এক্সিকিউটেবল শনাক্ত করতে সহায়তা করার, এবং এটি একটি কমই বিভিন্ন স্ক্রিপ্ট হিসাবে আপনি জানতে পারেন এর whichঅনেক বাণিজ্যিক Unices আজকাল (সোলারিস, এইচপি / ইউএক্স, AIX অথবা Tru64 মত) উপর।

এই স্ক্রিপ্টটি ব্যবহারকারীর পড়বে ~/.cshrc(সমস্ত cshস্ক্রিপ্টগুলির মতো এটি না করা ছাড়া csh -f), এবং প্রদত্ত কমান্ডের নাম (গুলি) উপাধিকার তালিকায় এবং $path(অ্যারে যে cshভিত্তিতে বজায় থাকে $PATH) সন্ধান করে।

আপনি এখানে যান, whichসেই সময়ে সর্বাধিক জনপ্রিয় শেলের জন্য প্রথম এসেছিলেন (এবং cshএটি 90-এর দশকের মাঝামাঝি পর্যন্ত জনপ্রিয় ছিল) এটি মূল কারণ যা এটি বইগুলিতে নথিভুক্ত হয়েছিল এবং এখনও বহুল ব্যবহৃত হয়।

মনে রাখবেন, এমনকি কোনও cshব্যবহারকারীর জন্যও , এই whichcsh স্ক্রিপ্টটি আপনাকে যথাযথভাবে সঠিক তথ্য দেয় না। এটি সংজ্ঞায়িতভাবে উপস্থাগুলি পায় যা ~/.cshrcআপনি পরে প্রম্পটে বা উদাহরণস্বরূপ sourceঅন্য কোনও cshফাইল আইং দ্বারা সংজ্ঞায়িত করেছেন এবং এটি (যদিও এটি ভাল ধারণা হবে না), এর PATHমধ্যে নতুন সংজ্ঞা দেওয়া যেতে পারে ~/.cshrc

whichবোর্ন শেল থেকে এই কমান্ডটি চালানো , এখনও আপনার মধ্যে সংজ্ঞায়িত এলিয়াসগুলির সন্ধান করবে ~/.cshrc, তবে যদি আপনি ব্যবহার না করেন এমন একটি না থাকে তবে cshসম্ভবত এটি আপনাকে সঠিক উত্তর পেতে পারে।

বিল্টিন typeকমান্ড সহ এসভিআর 2-তে 1984 পর্যন্ত বোর্ন শেলের সাথে অনুরূপ কার্যকারিতা যুক্ত হয়নি । যে এটি builtin আছে (একটি বহিস্থিত স্ক্রিপ্ট থেকে ভিন্ন) এর মানে হল যে এটা করতে ডান তথ্য (কিছুটা হলেও) দিতে যেমন শেলের অভ্যন্তরীণ অ্যাক্সেস আছে।

প্রাথমিক typeকমান্ডটি whichস্ক্রিপ্টের মতো একই সমস্যার মুখোমুখি হয়েছিল যাতে কমান্ডটি পাওয়া না গেলে এটি ব্যর্থতার প্রস্থান স্থিতি ফিরিয়ে দেয় না। এছাড়াও, এক্সিকিউটেবলের পক্ষে, বিপরীতে which, এটি এর ls is /bin/lsপরিবর্তে এমন কিছু আউটপুট দেয় /bin/lsযা স্ক্রিপ্টগুলিতে ব্যবহার করা কম সহজ করে তোলে।

ইউনিক্স সংস্করণ 8 এর (বন্যের মধ্যে প্রকাশিত হয়নি) বোর্ন শেলটির এটির নতুন typeনামকরণ হয়েছে whatis। এবং প্লান 9 (ইউনিক্সের একসাথে উত্তরসূরি) শেলটি rc(এবং এর ডেরিভেটিভগুলি এর মতো akangaএবং es) রয়েছে whatis

cshবোর্ন শেলের শীর্ষে অনেকগুলি বৈশিষ্ট্য (লাইন সম্পাদক, উপাধি ...) যুক্ত করেছেন, কর্ন শেল (একটি উপসেট যার মধ্যে পসিক্স শ সংজ্ঞা উপর ভিত্তি করে) ৮০-এর দশকের মাঝামাঝি সময়ে তৈরি হয়েছিল তবে ব্যাপকভাবে পাওয়া যায় না । এটা তার নিজের যোগ whence(ছাড়াও builtin type) যা বেশ কয়েকটি বিকল্প গ্রহণ ( -vসঙ্গে প্রদান type-একটি বাগাড়ম্বরপূর্ণ আউটপুট, এবং -pএক্সেকিউটেবল (না alias লেখা / ফাংশন ...) কেবল দেখুন)।

এটিএন্ডটি এবং বার্কলে-এর মধ্যে কপিরাইট সংক্রান্ত সমস্যার জন্য উদ্বেগের ঘটনাচক্রে, 80 এর দশকের গোড়ার দিকে 80 এর দশকের গোড়ার দিকে কয়েকটি ফ্রি সফটওয়্যার শেল বাস্তবায়ন প্রকাশিত হয়েছিল। অ্যালকুইস্ট শেলের সমস্ত (ছাই, বিএসডিগুলিতে বোর্ন শেল প্রতিস্থাপনের জন্য), ksh (pdksh) এর পাবলিক ডোমেন বাস্তবায়ন, bash(এফএসএফ দ্বারা স্পনসরিত), zsh1989 এবং 1991-এর মধ্যে প্রকাশিত হয়েছিল।

অ্যাশ, যদিও বোর্ন শেলের প্রতিস্থাপন বলে বোঝানো হয়েছে typeঅনেক পরে (নেটবিএসডি 1.3 এবং ফ্রিবিএসডি ২.৩ এ) অবধি বিল্টিন ছিল না, যদিও এটি ছিল hash -v। ওএসএফ / 1 /bin/shএর একটি typeবিল্টিন ছিল যা সর্বদা 0 ওএসএফ / 1 ভি 3.x এ ফিরে আসে। পাথ ( যেমনটি হবে ) মুদ্রণ করতে এবং সমস্ত ম্যাচিং কমান্ডের প্রতিবেদন করার জন্য একটি বিকল্প bashযোগ করা হয়নি । তৈরি builtin এবং যোগ কমান্ড মত অভিনয় এর । তাদের সব আছে।whence-ptypetype -pwhence -p-atcshwhichwherebashtype -azsh

fishশেল (2005) একটি আছে typeকমান্ড একটি ফাংশন হিসাবে প্রয়োগ করা।

whichCsh শেল স্ক্রিপ্ট এদিকে NetBSD বা থেকে অপসারণ করা হয়েছে (যেমন tcsh শেল এবং অন্যান্য শাঁস অনেক না ব্যবহারের builtin ছিল), এবং যোগ করা কার্যকারিতা whereis(যখন যেমন প্রার্থনা which, whereisমত আচরণ whichছাড়া এটি শুধুমাত্র এক্সেকিউটেবল আপ দেখায় $PATH)। ওপেনবিএসডি এবং ফ্রিবিএসডি-তে, whichসি-তে লেখা একটিতেও পরিবর্তন করা হয়েছিল যা $PATHকেবলমাত্র কমান্ড সন্ধান করে ।

বাস্তবায়নের

whichবিভিন্ন সিনট্যাক্স এবং আচরণ সহ বিভিন্ন ইউনিয়নে একটি কমান্ডের কয়েক ডজন বাস্তবায়ন রয়েছে ।

লিনাক্স অন (মধ্যে builtin বেশী পাশে tcshএবং zsh) আমরা বেশ কিছু বাস্তবায়নের পাবেন। উদাহরণস্বরূপ সাম্প্রতিক ডেবিয়ান সিস্টেমগুলিতে এটি একটি সাধারণ পসিক্স শেল স্ক্রিপ্ট যা এতে কমান্ড সন্ধান করে $PATH

busyboxএকটি whichকমান্ড আছে।

GNU whichসম্ভবত একটি অতি উত্তেজক একটি যা আছে । এটি whichঅন্যান্য শেলের সাথে সিএসএস স্ক্রিপ্ট কী করেছিল তা প্রসারিত করার চেষ্টা করে : আপনার এ্যালিয়াস এবং ফাংশন কী তা আপনি এটি বলতে পারেন যাতে এটি আপনাকে আরও ভাল উত্তর দিতে পারে (এবং আমি বিশ্বাস করি যে কিছু লিনাক্স ডিস্ট্রিবিউশনগুলি এটির জন্য কিছু বিশ্বব্যাপী উপাত্ত সেট bashকরে) ।

zshএক্সিকিউটেবলের পথে প্রসারিত করতে বেশ কয়েকটি অপারেটর রয়েছে : = ফাইলনাম এক্সপেনশন অপারেটর এবং :cহিস্টোরি এক্সপেনশন মডিফায়ার (এখানে প্যারামিটার বিস্তারের ক্ষেত্রে প্রয়োগ করা হয়েছে ):

$ print -r -- =ls
/bin/ls
$ cmd=ls; print -r -- $cmd:c
/bin/ls

zshমধ্যে zsh/parametersমডিউল নামেও কমান্ড হ্যাশ টেবিল তোলে commandsএসসিয়েতিভ আরে:

$ print -r -- $commands[ls]
/bin/ls

whatisউপযোগ (ইউনিক্স V8 বোর্ন শেল বা পরিকল্পনা 9 এক জন্য ব্যতীত rc/ es) সত্যিই এর সাথে সম্পর্কিত নয় এটি শুধুমাত্র ডকুমেন্টেশন জন্য হিসাবে (whatis ডাটাবেসের greps, যে man পৃষ্ঠা সারসংক্ষেপ 'হল)।

whereisএটি একই সাথে যুক্ত করা 3BSDহয়েছিল whichযদিও এটি লিখিত ছিল C, cshএকই সাথে নির্বাহযোগ্য, ম্যান পৃষ্ঠা এবং উত্সটি অনুসন্ধানের জন্য ব্যবহৃত হয়েছিল, তবে বর্তমান পরিবেশের উপর ভিত্তি করে নয়। সুতরাং আবার, এটি একটি পৃথক প্রয়োজনের জবাব দেয়।

এখন, স্ট্যান্ডার্ড ফ্রন্টে, পসআইএক্স command -vএবং -Vকমান্ডগুলি নির্দিষ্ট করে (যা পসিএক্সএক্স .২০০৮ পর্যন্ত alচ্ছিক ব্যবহৃত হত)। ইউএনআইএক্স typeকমান্ডটি নির্দিষ্ট করে (কোনও বিকল্প নেই)। এটা সমস্ত ( where, which, whenceকোন মান নির্দিষ্ট হয় না)

কিছু সংস্করণ পর্যন্ত, typeএবং command -vলিনাক্স স্ট্যান্ডার্ড বেস নির্দিষ্টকরণে alচ্ছিক ছিল যা ব্যাখ্যা করে যে উদাহরণস্বরূপ কিছু পুরানো সংস্করণ posh(যদিও pdkshউভয়টি ছিল তার ভিত্তিতে ) দুটি ছিল না didn't command -vকিছু বোর্ন শেল বাস্তবায়নেও যোগ করা হয়েছিল (সোলারিসের মতো)।

আজকের অবস্থা

আজকাল স্ট্যাটাসটি হ'ল typeএবং command -vবোর্নের মতো সমস্ত শেলগুলি সর্বব্যাপী (যদিও @ জার্নো দ্বারা উল্লিখিত হয়েছে, পোসিক্স bashমোডে না থাকলে বা মন্তব্যে নীচে অ্যালামকুইস্ট শেলের কিছু বংশধর না থাকলে সাবধানতা / বাগ নোট করুন )। tcshএকমাত্র শেল যেখানে আপনি ব্যবহার করতে চান which(যেমন সেখানে নেই typeএবং whichঅন্তর্নির্মিত নেই)।

ছাড়া অন্য শেল সালে tcshএবং zsh, whichআপনি যতদিন কোন ওরফে বা ফাংশন যা একই নামের আমাদের কোন আছে হিসেবে দেওয়া এক্সিকিউটেবল পথ বলতে পারে ~/.cshrc, ~/.bashrcবা কোন শেল প্রারম্ভকালে ফাইল এবং আপনি সংজ্ঞায়িত না $PATHআপনার ~/.cshrc। আপনার যদি কোনও এলিফ বা ফাংশন এর জন্য সংজ্ঞায়িত করা থাকে তবে এটি আপনাকে এটি সম্পর্কে বলতে বা নাও বলতে পারে, বা আপনাকে ভুল জিনিসটি বলতে পারে।

আপনি যদি কোনও নির্দিষ্ট নাম দিয়ে সমস্ত কমান্ড জানতে চান তবে বহনযোগ্য কিছুই নেই। আপনি এই ব্যবহার করতে চাই whereমধ্যে tcshবা zsh, type -abashবা zsh, whence -aksh93 এবং অন্যান্য শাঁস, আপনি ব্যবহার করতে পারেন typeএকযোগে সঙ্গে which -aযা কাজ করতে পারে।

প্রস্তাবনা

এক্সিকিউটেবলের কাছে পাথের নাম পাওয়া

এখন, স্ক্রিপ্টে এক্সিকিউটেবলের পাথের নাম পেতে, কয়েকটি ক্যাভেট রয়েছে:

ls=$(command -v ls)

এটি করার মানক উপায় হবে।

যদিও কয়েকটি সমস্যা রয়েছে:

  • কার্যকর না করে মৃত্যুদন্ড কার্যকর করার পথটি জানা সম্ভব নয়। সকল type, which, command -v... সমস্ত ব্যবহারের হিউরিস্টিক পথ খুঁজে বের করতে। তারা $PATHউপাদানগুলি লুপ করে এবং প্রথম নন-ডিরেক্টরি ফাইল খুঁজে পায় যার জন্য আপনি অনুমতি কার্যকর করেছেন। তবে শেলের উপর নির্ভর করে, কমান্ডটি কার্যকর করার ক্ষেত্রে, তাদের মধ্যে অনেকগুলি (বোর্ন, এটিএন্ডটি কেএস, জেডএস, অ্যাশ ...) ঠিক $PATHততক্ষণ তাদের ক্রিয়াকলাপ করবে যতক্ষণ না execveসিস্টেম কলটি ত্রুটি সহ ফিরে না আসে until । উদাহরণস্বরূপ যদি $PATHথাকে /foo:/barএবং আপনি কার্যকর করতে চান তবে lsতারা প্রথমে কার্যকর করার চেষ্টা করবে /foo/lsবা যদি এটি ব্যর্থ হয় /bar/ls। এখন মৃত্যুদণ্ড কার্যকর করা/foo/lsব্যর্থ হতে পারে কারণ আপনার মৃত্যুদণ্ডের অনুমতি না থাকলেও অন্যান্য অনেক কারণে, যেমন এটি কার্যকর বৈধ নয়। যদি আপনার জন্য মৃত্যুদন্ড কার্যকর করার অনুমতি থাকে command -v lsতবে প্রতিবেদন করবে তবে বৈধ কার্যকর কার্যকরযোগ্য না হলে দৌড়ানো আসলে চালানো হতে পারে ।/foo/ls/foo/lsls/bar/ls/foo/ls
  • যদি fooঅন্তর্নির্মিত বা ফাংশন বা উপন্যাস হয়, command -v fooফিরে আসে foo। সঙ্গে কিছু শাঁস পছন্দ ash, pdkshবা zsh, এটি ফেরত দিতে পারেন fooযদি $PATHখালি স্ট্রিং অন্তর্ভুক্ত এবং সেখানে একটি এক্সিকিউটেবল এর fooবর্তমান ডিরেক্টরির মধ্যে ফাইল। কিছু পরিস্থিতি রয়েছে যেখানে আপনার এটি বিবেচনার প্রয়োজন হতে পারে। উদাহরণস্বরূপ মনে রাখবেন যে বিল্টিনগুলির তালিকা শেল বাস্তবায়নের সাথে পরিবর্তিত হয় (উদাহরণস্বরূপ, mountকখনও কখনও ব্যস্তবক্সের জন্য অন্তর্নির্মিত sh) এবং উদাহরণস্বরূপ bashপরিবেশ থেকে ফাংশনগুলি পেতে পারে।
  • শেলের উপর নির্ভর করে যদি $PATHআপেক্ষিক পাথ উপাদানগুলি থাকে (সাধারণত .বা খালি স্ট্রিং যা উভয়ই বর্তমান ডিরেক্টরিকে নির্দেশ করে তবে কিছু হতে পারে) থাকতে পারে তবে এটি command -v cmdকোনও পরম পাথ আউটপুট নাও করতে পারে। সুতরাং আপনি চালনার সময় আপনি যে পথটি পেয়েছেন সেটি অন্য কোনও জায়গায় command -vআপনার পরে আর কার্যকর হবে cdনা।
  • অকল্পনীয়: ksh93 শেল সঙ্গে, যদি /opt/ast/bin(যদিও যে সঠিক পথ বিভিন্ন ব্যবস্থা আমি বিশ্বাস করি উপর বিভিন্ন রকমের হতে পারে) আপনি হয় $PATH, ksh93 প্রাপ্তিসাধ্য কিছু অতিরিক্ত builtins (করতে হবে chmod, cmp, cat...), কিন্তু command -v chmodফিরে আসবে /opt/ast/bin/chmodএমনকি যদি সেই পথ doesn ' অস্তিত্ব নেই

একটি কমান্ড বিদ্যমান কিনা তা নির্ধারণ করা হচ্ছে

প্রদত্ত আদেশটি মানকভাবে বিদ্যমান কিনা তা জানতে আপনি এটি করতে পারেন:

if command -v given-command > /dev/null 2>&1; then
  echo given-command is available
else
  echo given-command is not available
fi

যেখানে কেউ ব্যবহার করতে চাইবে which

(t)csh

ইন cshএবং tcsh, আপনার খুব পছন্দ নেই। ইন tcsh, যে যেমন সূক্ষ্ম whichbuiltin হয়। ইন csh, এটি হবে সিস্টেম whichকমান্ড, যা কিছু ক্ষেত্রে আপনি যা চান তা নাও করতে পারে।

কেবল কয়েকটি শেলের মধ্যে কমান্ডগুলি সন্ধান করুন

একটি ক্ষেত্রে যেখানে এটি ব্যবহার করতে জানার জন্য হতে পারে whichযদি আপনি সম্ভাব্য শেল builtins বা ফাংশন উপেক্ষা কমান্ড পথ জানতে চাই, bash, csh(না tcsh), dashঅথবা Bourneশেল স্ক্রিপ্ট, যে শাঁস আছে না whence -p(যেমন kshঅথবা zsh) , command -ev(যেমন yash), whatis -p( rc, akanga) বা একটি বিল্টিন which(যেমন tcshবা zsh) এমন সিস্টেমে যেখানে whichউপলব্ধ এবং cshস্ক্রিপ্টটি নয়।

যদি এই শর্তগুলি পূরণ হয় তবে:

echo=$(which echo)

আপনাকে প্রথমে পথ দিতে হবে echoমধ্যে $PATH(কোণ ক্ষেত্রে ব্যতীত), কিনা নির্বিশেষে echoএকটি শেল builtin / ওরফে / ফাংশন বা না হতে হবে।

অন্যান্য শেলগুলিতে, আপনি পছন্দ করবেন:

  • zsh : echo==echoবা echo=$commands[echo]বাecho=${${:-echo}:c}
  • ksh , zsh :echo=$(whence -p echo)
  • যশ :echo=$(command -ev echo)
  • আরসি , আকাঙ্গা : echo=`whatis -p echo`(স্পেস সহ রাস্তাগুলি থেকে সাবধান থাকুন)
  • মাছ :set echo (type -fp echo)

মনে রাখবেন যে আপনি যা করতে চান তা যদি সেই আদেশটি চালানো হয় তবে echoআপনাকে এর পথটি পেতে হবে না, আপনি কেবল এটি করতে পারেন:

env echo this is not echoed by the builtin echo

উদাহরণস্বরূপ, এর সাথে tcsh, বিল্টিন whichব্যবহার করা থেকে রোধ করতে :

set Echo = "`env which echo`"

যখন আপনার একটি বাহ্যিক কমান্ড দরকার হয়

আরেকটি ক্ষেত্রে যেখানে আপনি ব্যবহার করতে পারেন whichযখন আপনি আসলে প্রয়োজন একটি বহিস্থিত কমান্ড। পসিক্সের প্রয়োজন যে সমস্ত শেল বিল্টিনগুলি (যেমন command) বাহ্যিক কমান্ড হিসাবেও উপলব্ধ থাকে, তবে দুর্ভাগ্যক্রমে commandঅনেক সিস্টেমে এটি হয় না। উদাহরণস্বরূপ, commandলিনাক্স ভিত্তিক অপারেটিং সিস্টেমে কোনও কমান্ড পাওয়া বিরল, যখন তাদের বেশিরভাগের একটি whichকমান্ড থাকে (যদিও বিভিন্ন বিকল্প এবং আচরণের সাথে পৃথক পৃথক)।

যেসব ক্ষেত্রে আপনি বহিরাগত কমান্ড চাইতে পারেন সেখানে পসিক্স শেল না দিয়ে আপনি যেখানে কোনও আদেশ প্রয়োগ করবেন would

system("some command line"), popen()... C অথবা বিভিন্ন ভাষায় কার্যাবলী যে কমান্ড লাইন বিশ্লেষণ করতে একটি শেল ডাকা, তা করেন system("command -v my-cmd")তাদের মধ্যে কাজ। perlএটির একটি ব্যতিক্রম হ'ল যদি শেলটি কোনও বিশেষ চরিত্র (স্থান ব্যতীত) না দেখে শেলটিকে অনুকূল করে তোলে। এটি এর ব্যাকটিক অপারেটরের ক্ষেত্রেও প্রযোজ্য:

$ perl -le 'print system "command -v emacs"'
-1
$ perl -le 'print system ":;command -v emacs"'
/usr/bin/emacs
0

$ perl -e 'print `command -v emacs`'
$ perl -e 'print `:;command -v emacs`'
/usr/bin/emacs

:;উপরোক্ত যে সংযোজন perlসেখানে একটি শেল আহবান। ব্যবহার করে which, আপনাকে সেই কৌশলটি ব্যবহার করতে হবে না।


24
@ জো, অনেকগুলি বাণিজ্যিক ইউনিয়নের whichএকটি cshলিপি। কারণটি isতিহাসিক, এ কারণেই আমি ইতিহাস দিয়েছি, সুতরাং লোকেরা বুঝতে পারে যে এটি কোথা থেকে এসেছে, লোকেরা কেন এটি ব্যবহার করতে অভ্যস্ত হয়ে উঠল এবং আসলে এটি ব্যবহার করার আপনার কোনও কারণ নেই। এবং হ্যাঁ, কিছু লোক (টি) সিএসএস ব্যবহার করে। প্রত্যেকে এখনও লিনাক্স ব্যবহার করে না
স্টাফেন চেজেলাস

12
এই পোস্টটি পড়ার পরে, আমি উত্তরের জন্য অনেক প্রসঙ্গ খুঁজে পেয়েছি, তবে উত্তরটি নিজেই নয়। এই পোস্টে এটি যেখানে আপনি যে জিনিসগুলি ব্যবহার করার চেষ্টা করছেন , তার ইতিহাস , বাস্তবায়ন , সম্পর্কিত কাজগুলি করার জন্য অন্যান্য কমান্ড, বা প্রকৃতপক্ষে ব্যবহারের কারণগুলির বিপরীতে ব্যবহার করবেন না কেন তা আসলেই বলা আছে ? অন্য আদেশগুলি আরও ভাল কেন ? তারা কি থেকে পৃথক করে ? কীভাবে তারা এর ক্ষতিগুলি এড়াতে পারে? এই উত্তরটি আসলে সমস্যাগুলির তুলনায় বিকল্পগুলির সাথে সমস্যাগুলিতে আরও শব্দ ব্যয় করে । whichwhichwhichwhichwhichwhichwhich
ব্যবহারকারী 62251

1
উত্তর যা দাবি command -vকরে তার বিপরীতে, মৃত্যুর অনুমতি কার্যকর করার জন্য পরীক্ষা করে না, অন্ততপক্ষে যদি আপনি এটিকে কোনও পথ ছাড়াই বিশুদ্ধ ফাইল নাম যুক্তি দিয়ে কল করেন। আমি ড্যাশ 0.5.8 এবং জিএনইউ ব্যাশ 4.3.48 দ্বারা পরীক্ষা করেছি।
জার্নো

2
@ স্টাফেনচাজেলাস যদি আমি নতুন ফাইল তৈরি করি touch /usr/bin/mytestfileএবং তারপরে চালানো হয় command -v mytestfileতবে এটি পথ দেবে (যেখানে which mytestfileতা নেই)।
জার্নো

2
@ জারনো, ওহ হ্যাঁ, আপনি ঠিক বলেছেন bashযদি কোনও এক্সিকিউটেবল ফাইল না খুঁজে পায় তবে একটি নির্বাহযোগ্য ফাইলের মীমাংসা করবে, সুতরাং এটি "ঠিক আছে" (যদিও অনুশীলনে এটির পরিবর্তে command -v/ typeত্রুটি ফিরিয়ে দেবে ) এটি সেই আদেশ হিসাবে আপনি চালনা করার সময় কার্যকর করার চেষ্টা করবেন mytestfile, কিন্তু dashআচরণটি বগি, যেমন কোনও এক্সিকিউটেবলের cmdআগে অ-এক্সিকিউটেবল থাকে , command -vএক্সিকিউটেবলকে এক্সিকিউটেবলকে এক্সিকিউট করতে cmdপারে এমনটি ফিরিয়ে দেয় (ভুলটিও হ্যাশ হয়)। ফ্রিবিএসডি sh(এছাড়াও ভিত্তিক ash) একই বাগ রয়েছে। zsh, yash, ksh, mksh, bash as sh ঠিক আছে।
স্টাফেন চেজেলাস

47

যে কারণে কেন কেউ ব্যবহার করতে না চাইতে পারে সেগুলি whichইতিমধ্যে ব্যাখ্যা করা হয়েছে, তবে কয়েকটি সিস্টেমে এখানে কয়েকটি উদাহরণ দেওয়া আছে যেখানে whichবাস্তবে ব্যর্থ হয়।

বোর্ন-এর মতো শেলগুলিতে, আমরা আউটপুটটির whichসাথে আউটপুট তুলনা করছি type( typeশেল বিল্টিন হওয়া, এটি বোঝানো হচ্ছে স্থল সত্য, কারণ এটি শেলটি কীভাবে এটি আদেশ করবে তা আমাদের জানাচ্ছে)।

অনেকগুলি ক্ষেত্রে কর্নার কেস, তবে মনে রাখবেন যে which/ typeপ্রায়শই কর্নার ক্ষেত্রে ব্যবহৃত হয় (যেমন একটি অপ্রত্যাশিত আচরণের উত্তর খুঁজে পেতে: পৃথিবীতে কেন সেই আদেশ সেইরকম আচরণ করে, যা আমি বলছি? )।

বেশিরভাগ সিস্টেম, বেশিরভাগ বোর্নের মতো শেলস: ফাংশন

সর্বাধিক সুস্পষ্ট কেস ফাংশনগুলির জন্য:

$ type ls
ls is a function
ls ()
{
[ -t 1 ] && set -- -F "$@";
command ls "$@"
}
$ which ls
/bin/ls

কারণটি কেবল whichএক্সিকিউটেবল সম্পর্কে, এবং কখনও কখনও এলিয়াস সম্পর্কে রিপোর্ট করে (যদিও সবসময় আপনার শেলের মতো না), কার্যকারিতা নয়।

জিএনইউ যার ম্যান পেজটির একটি ভাঙ্গা রয়েছে (যেমন তারা উদ্ধৃতি দিতে ভুলে গেছে $@) উদাহরণটি কীভাবে এটি ফাংশনগুলি রিপোর্ট করতে ব্যবহার করতে হয়, তবে কেবলমাত্র এলিয়াসগুলির মতো, কারণ এটি শেল সিনট্যাক্স পার্সার বাস্তবায়ন করে না, এটি সহজেই বোকা:

$ which() { (alias; declare -f) | /usr/bin/which --tty-only --read-alias --read-functions --show-tilde --show-dot "$@";}
$ f() { echo $'\n}\ng ()\n{ echo bar;\n}\n' >> ~/foo; }
$ type f
f is a function
f ()
{
echo '
}
g ()
{ echo bar;
}
' >> ~/foo
}
$ type g
bash: type: g: not found
$ which f
f ()
{
echo '
}
$ which g
g ()
{ echo bar;
}

বেশিরভাগ সিস্টেম, বেশিরভাগ বোর্নের মতো শাঁস: বিল্টইনস

আরেকটি সুস্পষ্ট মামলা, builtins বা কীওয়ার্ড হিসাবে whichএকটি বহিস্থিত কমান্ড হচ্ছে জানেন যে কোন উপায়ে builtins আপনার শেল আছে আছে (এবং মত কিছু শাঁস zsh, bashবা kshপরিবর্তনশীল builtins লোড করতে পারেন):

$ type echo . time
echo is a shell builtin
. is a shell builtin
time is a shell keyword
$ which echo . time
/bin/echo
which: no . in (/bin:/usr/bin)
/usr/bin/time

(এটি zshযেখানে whichঅন্তর্নির্মিত সেখানে প্রযোজ্য না )

সোলারিস 10, এআইএক্স 7.1, এইচপি / ইউএক্স 11 আই, ট্রু 64 5.1 এবং আরও অনেকগুলি:

$ csh
% which ls
ls:   aliased to ls -F
% unalias ls
% which ls
ls:   aliased to ls -F
% ksh
$ which ls
ls:   aliased to ls -F
$ type ls
ls is a tracked alias for /usr/bin/ls

এটি কারণ বেশিরভাগ বাণিজ্যিক ইউনিয়নগুলিতে which( 3BSD- র মূল প্রয়োগের মতো) একটি cshস্ক্রিপ্ট যা পড়তে পারে ~/.cshrc। এটি যে এলিয়াসগুলির প্রতিবেদন করবে তা হ'ল সংজ্ঞায়িতগুলি হ'ল আপনি বর্তমানে যে সংজ্ঞাটি নির্ধারণ করেছেন এবং আপনি যে শেল ব্যবহার করছেন তা নির্বিশেষে।

এইচপি / ইউএক্স বা ট্রু 64 এ:

% echo 'setenv PATH /bin:/usr/bin' >> ~/.cshrc
% setenv PATH ~/bin:/bin:/usr/bin
% ln -s /bin/ls ~/bin/
% which ls
/bin/ls

(সোলারিস এবং এআইএক্স সংস্করণগুলি $pathপড়ার আগে সংরক্ষণ করে ~/.cshrcএবং কমান্ড (গুলি) সন্ধানের পূর্বে পুনরুদ্ধার করে এই সমস্যাটি সমাধান করেছে )

$ type 'a b'
a b is /home/stephane/bin/a b
$ which 'a b'
no a in /usr/sbin /usr/bin
no b in /usr/sbin /usr/bin

বা:

$ d="$HOME/my bin"
$ mkdir "$d"; PATH=$PATH:$d
$ ln -s /bin/ls "$d/myls"
$ type myls
myls is /home/stephane/my bin/myls
$ which myls
no myls in /usr/sbin /usr/bin /home/stephane/my bin

(অবশ্যই, cshস্ক্রিপ্ট হওয়ার কারণে আপনি এটি ফাঁকা স্থান যুক্তিগুলির সাথে কাজ করার আশা করতে পারবেন না ...)

CentOS 6.4, ব্যাশ

$ type which
which is aliased to `alias | /usr/bin/which --tty-only --read-alias --show-dot --show-tilde'
$ alias foo=': "|test|"'
$ which foo
alias foo=': "|test|"'
        /usr/bin/test
$ alias $'foo=\nalias bar='
$ unalias bar
-bash: unalias: bar: not found
$ which bar
alias bar='

সেই সিস্টেমে, একটি উপনাম সংজ্ঞায়িত সিস্টেম-প্রশস্ত সিস্টেম রয়েছে যা জিএনইউ whichকমান্ডটি মোড় করে ।

কারণ বাজে আউটপুট whichআউটপুট সার্চ bashএর aliasকিন্তু কিভাবে সঠিকভাবে এটা বিশ্লেষণ করতে জানে না এবং হিউরিস্টিক ব্যবহার (প্রতি লাইনে একটি ওরফে, প্রথমে একটি পরে কমান্ড পাওয়া জন্য দেখায় |, ;, &...)

সেন্টোসের সবচেয়ে খারাপ বিষয়টি হ'ল zshএকটি পুরোপুরি সূক্ষ্ম whichবিল্টিন কমান্ড রয়েছে তবে সেন্টোস এটি একটি জিএনইউ-তে একটি অ-কর্মজীবন ওরফে দিয়ে প্রতিস্থাপন করে তা ভেঙে ফেলতে সক্ষম হয়েছিল which

দেবিয়ান 7.0, কেএস 93:

(যদিও অনেক শেল সহ বেশিরভাগ সিস্টেমে প্রযোজ্য)

$ unset PATH
$ which which
/usr/local/bin/which
$ type which
which is a tracked alias for /bin/which

দেবিয়ান অন, /bin/whichএকটি /bin/shস্ক্রিপ্ট। আমার ক্ষেত্রে, shহচ্ছে dashকিন্তু এটি একই যখন এটা bash

একটি সেট না PATHনিষ্ক্রিয় করতে নয় PATHলুকআপ কিন্তু সিস্টেমের ব্যবহার মানে ডিফল্ট পাথে যা ডেবিয়ান উপর দুর্ভাগ্যবশত, কেউ উপর সম্মত ( dashএবং bashআছে /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin, zshআছে /bin:/usr/bin:/usr/ucb:/usr/local/bin, ksh93আছে /bin:/usr/bin, mkshআছে /usr/bin:/bin( $(getconf PATH)), execvp()মত ( env) আছে :/bin:/usr/bin(হ্যাঁ, বর্তমান ডিরেক্টরী প্রথম দেখায়! ))।

whichএটির কারণে এটি কেন ভুল হয় কারণ এটি এর dashডিফল্ট ব্যবহার করে PATHযা ksh93এর থেকে পৃথক

জিএনইউ এর সাথে এটির চেয়ে ভাল নয় whichযা রিপোর্ট করেছে:

which: no which in ((null))

(মজার বিষয় হল, /usr/local/bin/whichআমার সিস্টেমে আসলেই একটি রয়েছে যা আসলে একটি akangaস্ক্রিপ্ট এসেছিল akanga(এটি একটি rcশেল ডেরিভেটিভ যেখানে ডিফল্ট PATHহয় /usr/ucb:/usr/bin:/bin:.))

বাশ, যে কোনও সিস্টেম:

এক ক্রিস তার উত্তরে উল্লেখ করা হয় :

$ PATH=$HOME/bin:/bin
$ ls /dev/null
/dev/null
$ cp /bin/ls bin
$ type ls
ls is hashed (/bin/ls)
$ command -v ls
/bin/ls
$ which ls
/home/chazelas/bin/ls

hashম্যানুয়ালি কল করার পরেও :

$ type -a which
which is /usr/local/bin/which
which is /usr/bin/which
which is /bin/which
$ hash -p /bin/which which
$ which which
/usr/local/bin/which
$ type which
which is hashed (/bin/which)

এখন একটি ক্ষেত্রে যেখানে whichএবং কখনও কখনও typeব্যর্থ হয়:

$ mkdir a b
$ echo '#!/bin/echo' > a/foo
$ echo '#!/' > b/foo
$ chmod +x a/foo b/foo
$ PATH=b:a:$PATH
$ which foo
b/foo
$ type foo
foo is b/foo

এখন কিছু শাঁস সহ:

$ foo
bash: ./b/foo: /: bad interpreter: Permission denied

অন্যদের সাথে:

$ foo
a/foo

আমরাও whichনা typeঅগ্রিম যে জানতে পারেন b/fooমৃত্যুদন্ড কার্যকর করা যাবে না। কিছু শাঁস মত bash, kshবা yash, যখন invoking fooপ্রকৃতপক্ষে চালানোর চেষ্টা করবে b/fooঅন্যরা (যেমন, এবং একটি ত্রুটি প্রতিবেদন zsh, ash, csh, Bourne, tcsh) চালানো হবে a/fooব্যর্থতার উপর execve()সিস্টেম কল b/foo


mkshপ্রকৃতপক্ষে ডিফল্টর জন্য আলাদা কিছু ব্যবহার করে $PATH: প্রথমে, অপারেটিং সিস্টেমের সংকলন-সময় ধ্রুবক _PATH_DEFPATHব্যবহৃত হয় (বিএসডিগুলিতে সাধারণত) তবে confstr(_CS_PATH, …)ব্যবহৃত হয় (পসিক্স), এবং যদি উভয়ই উপস্থিত না থাকে বা ব্যর্থ /bin:/usr/bin:/sbin:/usr/sbinহয় তবে ব্যবহৃত হয়।
মীরাবিলোস

1
আপনার প্রথম উদাহরণে, lsএটি কোনও ফাংশন হলেও এটি lsপাঠ থেকে ব্যবহার করছে । আর whichতোমাকে বলতে যা এক ব্যবহৃত হয় জরিমানা /usr/bin/ls বা /usr/local/bin/ls। আমি দেখতে পাচ্ছি না "ব্যবহার কেন নয় যেটি" ....
rudimeier

@rudimeier, যে which lsআমাকে দিতে হবে /bin/lsকিনা নির্বিশেষে lsফাংশন কল /bin/lsবা /opt/gnu/bin/lsবা dirবা কিছুই। whichআইওডাব্লু , (যা বাস্তবায়ন করে, আইএমএমভি) অপ্রাসঙ্গিক কিছু দিচ্ছে
স্টাফেন চেজেলাস

1
@ StéphaneChazelas। না না না. আমি ইতিমধ্যে জানি যে আমার lsএকটি ফাংশন। আমি জানি যে আমার lsফাংশন কল করছে lsথেকে PATH। এখন whichফাইলটি কোথায় তা আমাকে বলুন। আপনি কেবলমাত্র একটি একক ব্যবহারের কেস দেখতে পান: "আমার শেলটি এই আদেশটি দিয়ে কী করবে। এই ব্যবহারের ক্ষেত্রে whichভুল, সঠিক। তবে অন্যান্য ব্যবহারের ক্ষেত্রেও রয়েছে (জিএনইউ) whichহুবহু সঠিক জিনিস।
rudimeier

@ রডিমিটার, whichপ্রয়োগের উপর নির্ভর করে । কেউ কেউ আপনাকে এটির একটি উপন্যাস বলবে (যদি আপনার কোনও একটি এলিফ কনফিগার করা থাকে, বা যদি ~/.cshrcআপনার বাড়ীতে এমন একটি উপনাম থাকে) তবে কেউ কেউ আপনাকে একটি পথ দেবে তবে কিছু শর্তে এটি ভুল। sh -c 'command -v ls', নিখুঁত না হলেও এখনও আপনাকে সেই বিভিন্ন প্রয়োজনের সঠিক উত্তর দেওয়ার সম্ভাবনা বেশি (এবং এটি মানকও)।
স্টাফেন চেজেলাস

21

একটি জিনিস যা (আমার দ্রুত স্কিম থেকে) মনে হচ্ছে যে স্টিফেন উল্লেখ করেন নি তা হ'ল whichআপনার শেলের পথের হ্যাশ টেবিল সম্পর্কে কোনও ধারণা নেই। এটির প্রভাব রয়েছে যে এটি কোনও ফলাফল ফিরে আসতে পারে যা আসলে কী সঞ্চালিত হয় তার প্রতিনিধিত্ব করে না, যা এটি ডিবাগিংয়ে অকার্যকর করে তোলে।


6

ইউনিক্স স্পিরিটে: প্রতিটি প্রোগ্রামকে একটি কাজ ভাল করে করুন।

যদি লক্ষ্যটির উত্তর দেওয়া হয়: এই নামের সাথে কোন নির্বাহযোগ্য ?

ডেবিয়ান সিস্টেমগুলির সাথে প্রদত্ত কোন এক্সিকিউটেবল প্রোগ্রামটি একটি ভাল উত্তর। যেটি সিএস প্রদান করেছিল তাতে আলিয়াস অন্তর্ভুক্ত ছিল, এটি সমস্যার উত্স। যা কিছু শাঁস অভ্যন্তরীণ অন্তর্নির্মিত হিসাবে সরবরাহ করে তার আলাদা লক্ষ্য রয়েছে। হয় সেই এক্সিকিউটেবল ব্যবহার করুন বা এই উত্তরের শেষে প্রদত্ত স্ক্রিপ্টটি ব্যবহার করুন।

যদি এই স্ক্রিপ্টটি ব্যবহার করা হয়, তবে এর উত্তরগুলি কী, তা পরিষ্কার, সরল এবং দরকারী is

এই গোলটি আপনার প্রশ্নের প্রথম বাক্যের সাথে মিলবে:

এক্সিকিউটেবলের পথ সন্ধান করার সময় ...…

আপনার যদি এমন একটি সিস্টেম থাকে যা বলা হয় যে এক্সিকিউটেবল নামে পরিচিত না হয় (বেশিরভাগ লিনাক্স সিস্টেমে একটি থাকে) আপনি PATH এ ~/bin/whichআগে একটি তৈরি করতে পারেন /bin/যাতে এই পোস্টের নীচের অংশের মতো ব্যক্তিগত এক্সিকিউটেবল ওভাররাইড সিস্টেম থাকে:

যে এক্সিকিউটেবল PATH- এ পাওয়া সমস্ত এক্সিকিউটেবলের তালিকা তৈরি করবে (ডিফল্টরূপে) । যদি কেবল প্রথমটির প্রয়োজন হয় তবে বিকল্পটি -fউপলব্ধ।


এই মুহুর্তে আমরা একটি অন্য লক্ষ্যে পড়ে যাই:

শেলটি কার্যকর করবে (পার্স করার পরে)

এটি আপনার দ্বিতীয় বাক্য থেকে এসেছে:

আপনি যদি ইউনিক্স শেলের একটি কমান্ডের নাম প্রবেশ করান তবে কি হবে তা পরীক্ষা করা হচ্ছে

এই দ্বিতীয় বিষয়টি একটি প্রশ্নের উত্তরের উত্তর খুঁজে পেতে চেষ্টা করেছে যার উত্তর দেওয়া বরং কঠিন। শেলগুলির বিভিন্ন দৃষ্টিভঙ্গি, কোণার কেস এবং (সর্বনিম্ন) বিভিন্ন ব্যাখ্যা রয়েছে। এতে যুক্ত হচ্ছে:

বিভিন্ন ইউটিলিটি রয়েছে (যা টাইপ, কমান্ড, কোথা থেকে, যেখানে, যেখানে, হোয়াটস, হ্যাশ, ইত্যাদি)।

এবং নিশ্চিত, সমস্ত প্রচেষ্টা সেই লক্ষ্যের সাথে মেলে।


কোনটি এড়িয়ে যাবেন?

আমরা প্রায়শই শুনি যা এড়ানো উচিত।

আমি অবাক: কেন এটি যদি বলা হয় যে ভাল whichকাজ করে (কমপক্ষে ডেবিয়ানে)?

ইউনিক্স স্পিরিটে: প্রতিটি প্রোগ্রামকে একটি কাজ ভাল করে করুন।

বহিরাগত প্রোগ্রাম whichএক জিনিস করছে: পাথ হিসাবে একই নাম আছে প্রথম এক্সিকিউটেবল খুঁজুন কমান্ডের নাম । এবং এটি যুক্তিসঙ্গতভাবে ভাল করছেন।

আমি অন্য কোনও প্রোগ্রাম বা ইউটিলিটি জানি না যা আরও বেশি মৌলিক উপায়ে এই প্রশ্নের উত্তর দেয়। যেমনটি, এটি দরকারী এবং প্রয়োজনে এটি ব্যবহার করা যেতে পারে।

নিকটতম বিকল্পটি বলে মনে হচ্ছে: command -pv commandNameতবে এটি বিল্টিন এবং এলিয়াস সম্পর্কেও প্রতিবেদন করবে। একই উত্তর নয়।

অবশ্যই, whichসীমিত, এটি সমস্ত প্রশ্নের উত্তর দেয় না , কোনও সরঞ্জাম এটি করতে পারে না (ভাল, এখনও না ...)। তবে এটি কার্যকর যখন প্রশ্নটির উত্তর দেওয়ার জন্য এটি তৈরি করা হয়েছিল উত্তরটি তৈরি করার জন্য তৈরি করা হয়েছিল (ঠিক উপরের একটি)। অনেকটা edসীমাবদ্ধ ছিল এবং তারপরে sedহাজির (বা vi/ vim)। বা awkলাইকটি সীমাবদ্ধ ছিল এবং পার্লকে উপস্থিত এবং প্রসারিত করা হয়েছিল। তবুও, ed, sedঅথবা / এবং awkযেখানে নির্দিষ্ট ব্যবহারের ক্ষেত্রে আছে vimবা perlহয় না সেরা সরঞ্জাম।

কেন?

সম্ভবত কারণ whichশেল ব্যবহারকারীরা যে প্রশ্ন জিজ্ঞাসা করতে পারে তার কেবলমাত্র একটি অংশের উত্তর দেয়:

আমি যখন কমান্ডনেম টাইপ করি তখন কী সম্পাদিত হয়?


বাহ্যিক যা

যা বহিরাগত নির্বাহযোগ্য হিসাবে উপলব্ধ (অনেক সিস্টেমে) হওয়া উচিত।
বাহ্যিক সরঞ্জামটি কল করার একমাত্র নিশ্চিত উপায় হ'ল শেল থেকে বেরিয়ে আসার জন্য env ব্যবহার করা এবং তারপরে কল করা which(যা সমস্ত শেলগুলিতে কাজ করে):

 $ env which which
 /usr/bin/which

বা সম্পূর্ণ পথ ব্যবহার করুন which(যা বিভিন্ন সিস্টেমে পরিবর্তিত হতে পারে):

 /usr/bin/which which 

কেন এটি hackপ্রয়োজন? কারণ কিছু শাঁস (বিশেষত zsh) লুকায় which:

 $ zsh -c 'which which'
 which: shell built-in command

একটি হচ্ছে বাহ্যিক টুল (যেমন env) পুরোপুরি ব্যাখ্যা দিয়েছে কেন এটা শেল অভ্যন্তরীণ তথ্য রিপোর্ট করা হবে না। এলিয়াস, ফাংশন, বিল্টিনস, বিশেষ বিল্টিনস, শেল (অ-এক্সপোর্ট করা) ভেরিয়েবল ইত্যাদির মতো:

 $ env which ls
 /usr/bin/ls
 $ env which ll       # empty output

ll(এর জন্য একটি সাধারণ নাম ll='ls -l') খালি আউটপুট ইঙ্গিত দেয় যে llএক্সিকিউটেবল প্রোগ্রামের সাথে সম্পর্কিত নয়, বা কমপক্ষে, llPATH- তে কোনও এক্সিকিউটেবল ফাইল নেই । ব্যবহারের llক্ষেত্রে অন্য কিছু কল করা উচিত, এক্ষেত্রে একটি উপনাম:

 $ type ll
 ll is aliased to `ls -l'

type এবং command

আদেশগুলি typeএবং command -vপসিক্স দ্বারা অনুরোধ করা হয়েছে। এগুলি বেশিরভাগ শেলগুলিতে কাজ করার আশা করা উচিত এবং তারা সিএসএস, টিসিএসএস, মাছ এবং আরসি বাদে করে।

উভয় কমান্ডই অন্য আদেশটি কার্যকর করতে ব্যবহৃত হবে যার আদেশটি কার্যকর করা হবে।

whence, where, whereis, whatis,hash

তারপর, আছে whence, where, whereis, whatis, hash, এবং কিছু অন্যদের। অনুরূপ প্রশ্নের সমস্ত বিভিন্ন উত্তর। সমস্ত বিভিন্ন শেল বিভিন্ন উপায়ে কাজ। সম্ভবত, এর whenceপরে সবচেয়ে সাধারণ type। অন্যরা হ'ল বিশেষ সমাধান যা একই প্রশ্নের বিভিন্নভাবে উত্তর দেয়।

পরিবর্তে আমাদের কী ব্যবহার করা উচিত?

সম্ভবত whichপ্রথম জানতে যদি নামে একটি এক্সিকিউটেবল বিদ্যমান commandName , তারপর typeএবং commandতারপর, যদি commandName এখনো পাওয়া হয়নি: whence, where, whereis, whatis, hashযাতে।


whichএক্সিকিউটেবলের জন্য শেল স্ক্রিপ্ট ।

#! /bin/sh
set -ef; oldIFS=$IFS; IFS=:

say()( IFS=" "; printf "%s\n" "$*"; )
say "Simplified version of which."
usage(){ say Usage: "$0" [-f] args; }
if [ "$#" -eq 0 ]; then say Missing argument(s); usage; exit 2; fi

firstmatch=0
while getopts f whichopts; do
    case "$whichopts" in
        f) firstmatch=1 ;;
        ?) usage; exit 3 ;;
    esac
done
[ "$OPTIND" -gt 1 ] && shift `expr "$OPTIND" - 1`

allret=0; [ "$#" -eq 0 ] && allret=1
for program in "$@"; do
    ret=1
    for element in $PATH''; do
        case "$program" in
            */*) element="$program"; loop=0;;
            *)   element="${element:-.}/$program"; loop=1;;
        esac
        if [ -f "$element" ] && [ -x "$element" ]; then
            say "$element"
            ret=0
            if [ "$firstmatch" -eq 1 ] || [ "$loop" -eq 0 ]; then break; fi
        fi
    done
    [ "$ret" -eq 1 ] && allret=1
done

IFS="$oldIFS"
exit "$allret"

0

আমরা প্রায়শই শুনি যা এড়ানো উচিত। কেন? পরিবর্তে আমাদের কী ব্যবহার করা উচিত?

আমি যে শুনতে না। নির্দিষ্ট উদাহরণ প্রদান করুন। আমি আপনার লিনাক্স বিতরণ এবং ইনস্টল করা সফ্টওয়্যার প্যাকেজগুলির বিষয়ে উদ্বিগ্ন হব, whichকোথা থেকে আসে!

SLES 11.4 x86-64

টিসিএস সংস্করণে 6.18.01:

> which which

which: shell built-in command.

বাশ সংস্করণে ৩.২-১77:

> which which

/usr/bin/which

> which -v

GNU which v2.19, Copyright (C) 1999 - 2008 Carlo Wood.
GNU which comes with ABSOLUTELY NO WARRANTY;
This program is free software; your freedom to use, change
and distribute this program is protected by the GPL.

whichঅংশ util-লিনাক্স একটি প্রমিত প্যাকেজ Linux অপারেটিং সিস্টেমের অংশ হিসাবে ব্যবহারের জন্য লিনাক্স কার্নেল সংস্থার বিতরণ করেন। এটি এই অন্যান্য ফাইলগুলি সরবরাহ করে

/bin/dmesg
/bin/findmnt
/bin/logger
/bin/lsblk
/bin/more
/bin/mount
/bin/umount
/sbin/adjtimex
/sbin/agetty
/sbin/blkid
/sbin/blockdev
/sbin/cfdisk
/sbin/chcpu
/sbin/ctrlaltdel
/sbin/elvtune
/sbin/fdisk
/sbin/findfs
/sbin/fsck
/sbin/fsck.cramfs
/sbin/fsck.minix
/sbin/fsfreeze
/sbin/fstrim
/sbin/hwclock
/sbin/losetup
/sbin/mkfs
/sbin/mkfs.bfs
/sbin/mkfs.cramfs
/sbin/mkfs.minix
/sbin/mkswap
/sbin/nologin
/sbin/pivot_root
/sbin/raw
/sbin/sfdisk
/sbin/swaplabel
/sbin/swapoff
/sbin/swapon
/sbin/switch_root
/sbin/wipefs
/usr/bin/cal
/usr/bin/chrp-addnote
/usr/bin/chrt
/usr/bin/col
/usr/bin/colcrt
/usr/bin/colrm
/usr/bin/column
/usr/bin/cytune
/usr/bin/ddate
/usr/bin/fallocate
/usr/bin/flock
/usr/bin/getopt
/usr/bin/hexdump
/usr/bin/i386
/usr/bin/ionice
/usr/bin/ipcmk
/usr/bin/ipcrm
/usr/bin/ipcs
/usr/bin/isosize
/usr/bin/line
/usr/bin/linux32
/usr/bin/linux64
/usr/bin/look
/usr/bin/lscpu
/usr/bin/mcookie
/usr/bin/mesg
/usr/bin/mkzimage_cmdline
/usr/bin/namei
/usr/bin/rename
/usr/bin/renice
/usr/bin/rev
/usr/bin/script
/usr/bin/scriptreplay
/usr/bin/setarch
/usr/bin/setsid
/usr/bin/setterm
/usr/bin/tailf
/usr/bin/taskset
/usr/bin/time
/usr/bin/ul
/usr/bin/uname26
/usr/bin/unshare
/usr/bin/uuidgen
/usr/bin/wall
/usr/bin/whereis
/usr/bin/which
/usr/bin/write
/usr/bin/x86_64
/usr/sbin/addpart
/usr/sbin/delpart
/usr/sbin/fdformat
/usr/sbin/flushb
/usr/sbin/freeramdisk
/usr/sbin/klogconsole
/usr/sbin/ldattach
/usr/sbin/partx
/usr/sbin/rcraw
/usr/sbin/readprofile
/usr/sbin/rtcwake
/usr/sbin/setctsid
/usr/sbin/tunelp

আমার util-linuxসংস্করণ 2.19। রিলিজ নোটগুলি সহজেই তারিখের (২২-আগস্ট -2007) v2.13 এ ফিরে পাওয়া যাবে। এর বিন্দু বা লক্ষ্যটি কী তা নিশ্চিত নয়, এটি অবশ্যই 331 বার উর্ধ্বে লম্বা জিনিসটিতে উত্তর দেওয়া হয়নি।


2
লক্ষ্য করুন যে কীভাবে প্রশ্নটি ইউনিক্সকে বোঝায় তাতে কোন উল্লেখ নেই। লিনাক্স কয়েকটি মাত্র একটি।
কুসালানন্দ

2
আপনার which -vশো হিসাবে , এটি জিএনইউ যা (অপ্রতিরোধ্য একজন অন্য উত্তরে উল্লিখিত এবং কোনওভাবেই লিনাক্সের সাথে নির্দিষ্ট নয়), ইউএফ-লিনাক্স নয় যা এএফআইকে কখনও কোনও whichইউটিলিটি অন্তর্ভুক্ত করে না । util-লিনাক্স 2.19, 2011 থেকে গনুহ যা 2.19 2008. থেকে
Stéphane Chazelas
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.