বাশ স্ক্রিপ্ট থেকে কোনও প্রোগ্রাম উপস্থিত রয়েছে কিনা তা আমি কীভাবে পরীক্ষা করতে পারি?


2206

আমি কীভাবে কোনও প্রোগ্রামের উপস্থিতি যাচাই করব যে এমনভাবে কোনও ত্রুটি ফিরে আসবে এবং প্রস্থান করবে বা স্ক্রিপ্টটি দিয়ে চালিয়ে যাবে?

মনে হয় এটি সহজ হওয়া উচিত, তবে এটি আমাকে স্টাম্পিং করে চলেছে।


একটি "প্রোগ্রাম" কি? এটিতে ফাংশন এবং উপকরণগুলি অন্তর্ভুক্ত রয়েছে? whichএই জন্য সত্য ফিরে। typeযুক্তি ব্যতীত অতিরিক্ত সংরক্ষিত শব্দ এবং শেল বিল্টিনগুলির জন্য সত্য ফিরে আসবে। যদি "প্রোগ্রাম" এর অর্থ "এক্সকিউটেবল ইন $PATH" হয়, তবে এই উত্তরটি দেখুন
টম হেল

উত্তর:


3045

উত্তর

পসিক্স সামঞ্জস্যপূর্ণ:

command -v <the_command>

বাশ নির্দিষ্ট পরিবেশের জন্য:

hash <the_command> # For regular commands. Or...
type <the_command> # To check built-ins and keywords

ব্যাখ্যা

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

যত্ন কেন?

  • অনেক অপারেটিং সিস্টেমে এমন একটি থাকে whichযা একটি প্রস্থান স্থিতিও নির্ধারণ করে না , অর্থ এটি if which fooসেখানে কাজ করবে না এবং সর্বদাfoo উপস্থিত রয়েছে বলেও রিপোর্ট করবে (এটি মনে রাখবেন যে কিছু পসিক্স শেলও এটি করার জন্য উপস্থিত রয়েছে hash)।
  • অনেক অপারেটিং সিস্টেমগুলি whichকাস্টম এবং অশুভ জিনিসগুলি যেমন আউটপুট পরিবর্তন করতে এমনকি প্যাকেজ ম্যানেজারে হুক করে।

সুতরাং, ব্যবহার করবেন না which। পরিবর্তে এর মধ্যে একটি ব্যবহার করুন:

$ command -v foo >/dev/null 2>&1 || { echo >&2 "I require foo but it's not installed.  Aborting."; exit 1; }
$ type foo >/dev/null 2>&1 || { echo >&2 "I require foo but it's not installed.  Aborting."; exit 1; }
$ hash foo 2>/dev/null || { echo >&2 "I require foo but it's not installed.  Aborting."; exit 1; }

(মাইনর পার্শ্ব-দ্রষ্টব্য: কিছু সুপারিশ করবে 2>&-একই 2>/dev/nullকিন্তু ছোট - এই অসত্য2>&-বন্ধ এফডি 2 যা ঘটায় ত্রুটি প্রোগ্রামে যখন এটি দ্বারা stderr, যা সফলভাবে লিখিতভাবে এবং আউটপুট খারিজ থেকে ভিন্ন লিখতে চেষ্টা করে (এবং বিপজ্জনক!))

যদি আপনার হ্যাশ ব্যাং হয় /bin/shতবে পসিক্স কী বলে তা আপনার যত্ন নেওয়া উচিত। typeএবং hashএর প্রস্থান কোডগুলি পসিক্স দ্বারা ভয়ঙ্করভাবে সংজ্ঞায়িত করা হয় নি, এবং hashকমান্ডটি উপস্থিত না থাকলে সফলভাবে প্রস্থান করতে দেখা যায় (এটি typeএখনও দেখেনি )। commandএর প্রস্থান স্থিতিটি পসিক্স দ্বারা ভালভাবে সংজ্ঞায়িত করা হয়েছে, যাতে সম্ভবত এটি ব্যবহার করা সবচেয়ে নিরাপদ।

আপনার স্ক্রিপ্টটি ব্যবহার করে bashযদিও, POSIX নিয়ম সত্যিই ব্যাপার আর না এবং উভয় typeএবং hashপুরোপুরি ব্যবহার করা নিরাপদ হয়ে ওঠে। typeএখন -Pকেবল অনুসন্ধান করতে হবে PATHএবং hashএর পার্শ্ব-প্রতিক্রিয়া রয়েছে যা কমান্ডের অবস্থানটি হ্যাশ হয়ে যাবে (পরের বার আপনি এটি ব্যবহার করার জন্য দ্রুত অনুসন্ধানের জন্য) যা সাধারণত এটি একটি ভাল জিনিস যেহেতু আপনি সম্ভবত এটির ব্যবহারের জন্য তার অস্তিত্বের জন্য যাচাই করেছেন ।

একটি সাধারণ উদাহরণ হিসাবে, এখানে এমন একটি ফাংশন রয়েছে যা gdateএটি উপস্থিত থাকলে চলে, অন্যথায় date:

gnudate() {
    if hash gdate 2>/dev/null; then
        gdate "$@"
    else
        date "$@"
    fi
}

34
@ জিয়ার্ট: 'foo' বিদ্যমান না থাকলে &> / dev / নাল অংশটি 'টাইপ' প্রকাশ করে বার্তাটি লুকায়। প্রতিধ্বনিতে> & 2 মানক আউটপুটের পরিবর্তে ত্রুটি বার্তাটি স্ট্যান্ডার্ড ত্রুটিতে প্রেরণ নিশ্চিত করে; কারণ যে সম্মেলন। এগুলি উভয়ই আপনার টার্মিনালে উপস্থিত হয়, তবে ত্রুটি বার্তা এবং অপ্রত্যাশিত সতর্কতার জন্য মানক ত্রুটি অবশ্যই পছন্দসই আউটপুট।
lhunath

5
-P পতাকা 'SH' থেকে কাজ, যেমন না stackoverflow.com/questions/2608688/...
momeara

128
বাশে 'অগ্রণী' আই / ও পুনঃনির্দেশের সাথে অপরিচিতদের জন্য: 1) 2>&- ("ক্লোজ আউটপুট ফাইল ডেস্ক্রিপ্টর 2", যা স্ট্যাডার) এর একই ফলাফল রয়েছে 2> /dev/null; 2) >&2হ'ল একটি শর্টকাট 1>&2, যা আপনি "স্টাডারকে স্টার্ডারে পুনর্নির্দেশ" হিসাবে স্বীকৃতি দিতে পারেন। আরও তথ্যের জন্য উন্নত বাশ স্ক্রিপ্টিং গাইড i / o পুনঃনির্দেশ পৃষ্ঠাটি দেখুন।
মাইকওয়াটার

9
@ মাইকেওয়াটারস এ বি এস মোটামুটি উন্নত দেখায় এবং ব্যাশ এবং নন-ব্যাশ সিএলআই কার্যকারিতার বিস্তৃত বর্ণনা দেয় তবে এটি অনেক দিক থেকে খুব অবহেলা এবং ভাল অনুশীলন অনুসরণ করে না। একটি লেখার জন্য আমার এই মন্তব্যে প্রায় পর্যাপ্ত জায়গা নেই; কিন্তু আমি খারাপ কোড কয়েক র্যান্ডম উদাহরণ আটকে দিতে পারেন: while read element ; do .. done <<< $(echo ${ArrayVar[*]}), for word in $(fgrep -l $ORIGINAL *.txt), ls -l "$directory" | sed 1d , {{জন্য একটি seq $BEGIN $END}}, ... বহু লেখক সঙ্গে যোগাযোগ করুন এবং উন্নতি উত্থাপন করা চেষ্টা করেছি কিন্তু এটা কোন উইকি এবং অনুরোধ বধির কান অবতরণ করেছে।
lhunath

56
@mikewaters 2>&-হয় না হিসাবে একই 2>/dev/null। প্রাক্তন ফাইল বর্ণনাকারী বন্ধ করে দেয়, তবে পরেরটি কেবল এটিকে পুনর্নির্দেশ করে /dev/null। আপনি কোনও ত্রুটি দেখতে পাবেন না কারণ প্রোগ্রামটি আপনাকে স্ট্যাডারে আপনাকে জানানোর চেষ্টা করে যে স্ট্যাডার বন্ধ রয়েছে।
nyuszika7h

573

কমান্ডের উপস্থিতি রয়েছে $PATH এবং তা কার্যকরযোগ্য কিনা তা যাচাই করার জন্য নিম্নলিখিতটি একটি পোর্টেবল উপায় :

[ -x "$(command -v foo)" ]

উদাহরণ:

if ! [ -x "$(command -v git)" ]; then
  echo 'Error: git is not installed.' >&2
  exit 1
fi

এক্সিকিউটেবল চেক প্রয়োজন কারণ ব্যাশ একটি অ-এক্সিকিউটেবল ফাইল ফিরিয়ে দেয় যদি সেই নামের সাথে কোনও এক্সিকিউটেবল ফাইল না পাওয়া যায় $PATH

এছাড়াও মনে রাখবেন যে এক্সিকিউটেবলের একই নামযুক্ত কোনও অ-এক্সিকিউটেবল ফাইল যদি আগে বিদ্যমান থাকে তবে $PATHড্যাশ পূর্বেরটিকে কার্যকর করে দেয়, যদিও পরবর্তীটি কার্যকর করা হত। এটি একটি ত্রুটি এবং POSIX মান লঙ্ঘন করছে। [ বাগ রিপোর্ট ] [ মানক ]

এছাড়াও, আপনি যে কমান্ডটির সন্ধান করছেন সেটি একটি উপাধিকার হিসাবে সংজ্ঞায়িত করা থাকলে এটি ব্যর্থ হবে।


4
command -vঅ-এক্সিকিউটেবল ফাইলের জন্যও কোনও পথ তৈরি করবে ? যে, -x সত্যিই প্রয়োজনীয়?
einpoklum

5
@ আইনপোকলুম -xপরীক্ষা করে দেখায় যে ফাইলটি কার্যকর হয়, যা প্রশ্নটি ছিল।
কেন শার্প

3
@ কেনসার্প: তবে এটি অপ্রয়োজনীয় বলে মনে হচ্ছে, যেহেতু commandএটি নিজে কার্যকর করার জন্য পরীক্ষা করবে - তাই না?
einpoklum

13
@ আইনপোকলুম হ্যাঁ, এটি প্রয়োজনীয়। প্রকৃতপক্ষে, এমনকি এই সমাধানটি একটি প্রান্ত ক্ষেত্রে ভেঙে যেতে পারে। এটা আমার নজরে আনার জন্য ধন্যবাদ। $PATHকোনও কমান্ড কার্যকর করার সময় ড্যাশ, ব্যাশ এবং জ্যাশ সমস্ত অ-এক্সিকিউটেবল ফাইলের বাইরে যান । তবে এর আচরণটি command -vঅত্যন্ত বেমানান। ড্যাশ এ, এটি নির্বাহযোগ্য $PATHকিনা তা নির্বিশেষে এটি প্রথম মেলানো ফাইলটি ফেরত দেয় । ব্যাশে এটি প্রথম সম্পাদনযোগ্য ম্যাচটি ফেরত দেয় $PATH, তবে যদি কিছুই না থাকে তবে এটি একটি এক্সিকিউটেবল ফাইলটি ফিরিয়ে দিতে পারে। এবং zsh এ এটি কখনই কোনও এক্সিকিউটেবল ফাইল ফিরিয়ে দেবে না।
nyuszika7h

4
আমি যতটুকু বলতে পারি, dashএই তিনটির মধ্যে কেবলমাত্র একজনই যে নন-পসিক্স-সম্মতিযুক্ত; [ -x "$(command -v COMMANDNAME)"]অন্য দুটিতে কাজ করবে। দেখে মনে হচ্ছে এই বাগটি ইতিমধ্যে প্রতিবেদন করা হয়েছে তবে এখনও তার কোনও প্রতিক্রিয়া পাওয়া যায় নি: bugs.debian.org/cgi-bin/bugreport.cgi?bug=874264
nyuszika7h

208

আমি লুনাথের ব্যবহারকে নিরুৎসাহিত করার সাথে একমত whichএবং তার সমাধান ব্যাশ ব্যবহারকারীদের জন্য পুরোপুরি বৈধ । তবে আরও পোর্টেবল command -vহওয়ার জন্য এর পরিবর্তে ব্যবহৃত হবে:

$ command -v foo >/dev/null 2>&1 || { echo "I require foo but it's not installed.  Aborting." >&2; exit 1; }

কমান্ডটি commandপসিক্সের অনুগত। এর নির্দিষ্টকরণের জন্য এখানে দেখুন: কমান্ড - একটি সাধারণ কমান্ড চালান exec

দ্রষ্টব্য: typeপসিক্স অনুগত, তবে type -Pতা নয়।


3
উপরের মতো একই - exit 1;সেখান থেকে আহবান করা হলে একটি এক্সটার্ম মেরে ফেলে।
ব্যবহারকারী অজানা

1
এটি কোনও স্ট্যান্ডার্ড sh এ কাজ করবে না: আপনি &> কোনও বৈধ পুনঃনির্দেশ নির্দেশিকা নয়।
jyvenard

7
@ জ্যাভেনার্ড: প্রশ্নটিকে ট্যাগ করা বাশ , তাই আরও সংক্ষিপ্ত বাশ-নির্দিষ্ট পুনর্নির্দেশের স্বরলিপি &>/dev/null। যাইহোক, আমি আপনার সাথে একমত হইলাম, যা যা সত্যই গুরুত্বপূর্ণ তা বহনযোগ্যতা, আমি সেই অনুসারে আমার উত্তর সম্পাদনা করেছি, এখন স্ট্যান্ডার্ড শ রিডাইরেক্ট ব্যবহার করে >/dev/null 2>&1
গ্রেগভি

এমনকি এই উত্তরটির আরও উন্নতি করার জন্য আমি দুটি জিনিস করব: 1: জোশের উত্তরের মতো এটিকে সরল করতে "&>" ব্যবহার করুন। 2:
পাঠ্যযোগ্যতার

যদি কেউ এটি চায় তবে আমি কেবল এই একটি লাইনারটিকে
সমান

94

আমার .bashrc এ একটি ফাংশন সংজ্ঞায়িত করা হয়েছে যা এটি আরও সহজ করে তোলে।

command_exists () {
    type "$1" &> /dev/null ;
}

এটি কীভাবে ব্যবহৃত হয় তার একটি উদাহরণ এখানে রয়েছে (আমার কাছ থেকে .bash_profile)

if command_exists mvim ; then
    export VISUAL="mvim --nofork"
fi

কি করে &>?
সাদ মালিক


&>আপনার বাশের সংস্করণে উপলভ্য নাও হতে পারে। মার্সেলো কোড ভাল কাজ করা উচিত; এটি একই জিনিস করে।
জোশ স্ট্রেটার 1

3
বিল্টিন এবং সংরক্ষিত শব্দের ব্যর্থতা: thenউদাহরণ দিয়ে শব্দটি দিয়ে এটি ব্যবহার করে দেখুন। আপনার যদি নির্বাহের অস্তিত্বের প্রয়োজন হয় তবে এই উত্তরটি দেখুন $PATH
টম হেল

84

এটি $PATHভেরিয়েবলের যে কোনও ডিরেক্টরিতে এটি বিদ্যমান কিনা তা আপনি জানতে চান কিনা বা আপনি এর পরম অবস্থানটি জানেন কিনা তা নির্ভর করে depends এটি $PATHভেরিয়েবলটিতে রয়েছে কিনা তা জানতে চাইলে ব্যবহার করুন

if which programname >/dev/null; then
    echo exists
else
    echo does not exist
fi

অন্যথায় ব্যবহার

if [ -x /path/to/programname ]; then
    echo exists
else
    echo does not exist
fi

/dev/null/প্রথম উদাহরণে পুনঃনির্দেশটি whichপ্রোগ্রামটির আউটপুটকে দমন করে ।


22
আপনি আমার মন্তব্যে বর্ণিত কারণগুলির জন্য সত্যই "যা" ব্যবহার করা উচিত নয়।
লুুনাথ

39

@ লুনাথ এবং @ গ্রেগভির উত্তরগুলিতে প্রসারিত করে, এখানে এমন লোকদের কোড যা এই ifবিবরণীর ভিতরে সহজেই এই চেকটি রাখতে চান :

exists()
{
  command -v "$1" >/dev/null 2>&1
}

এটি কীভাবে ব্যবহার করবেন তা এখানে:

if exists bash; then
  echo 'Bash exists!'
else
  echo 'Your system does not have Bash'
fi

13
শিখতে ও উন্নত করার ইচ্ছাকে পুরস্কৃত করতে হবে। +1 এটি পরিষ্কার এবং সহজ। কেবলমাত্র আমি যুক্ত করতে পারি তা হ'ল commandএমনকি এলিয়াসগুলির ক্ষেত্রেও সফল হয় , যা কিছুটা বিপরীত হতে পারে। একটি ইন্টারেক্টিভ শেলটিতে অস্তিত্বের জন্য অনুসন্ধান করা যখন আপনি এটি কোনও স্ক্রিপ্টে স্থানান্তরিত করেন তখন থেকে আলাদা ফলাফল দেওয়া হবে।
প্লেক

1
আমি ঠিক পরীক্ষা করেছি এবং shopt -u expand_aliasesউপেক্ষা উপেক্ষা / লুকিয়ে রাখি ( alias ls='ls -F'অন্য উত্তরে উল্লিখিত মত ) এবং এর shopt -s expand_aliasesমাধ্যমে তাদের সমাধান করেছি command -v। সুতরাং সম্ভবত এটি চেকের আগে সেট করা উচিত এবং পরে আনসেট করা উচিত, যদিও এটি ফাংশন রিটার্ন মানকে প্রভাবিত করতে পারে যদি আপনি কমান্ড কলের আউটপুটকে স্পষ্টভাবে ক্যাপচার না করে এবং ফিরিয়ে না দেন।
ড্রাগন 788

24

ব্যবহার করার চেষ্টা করুন:

test -x filename

অথবা

[ -x filename ]

শর্তাধীন অভিব্যক্তিগুলির অধীনে বাশ ম্যানপেজ থেকে :

 -x file
          True if file exists and is executable.

26
তার মানে আপনাকে ইতিমধ্যে অ্যাপ্লিকেশনটির পুরো পথটি জানতে হবে।
lhunath

12
ওপি নির্দিষ্টভাবে বা কোনও এক্সিকিউটেবল উদাহরণের জন্য যাচাই করতে চেয়েছিল কিনা তা নির্দিষ্ট করে দেয় না ... আমি যেভাবে পড়লাম সেভাবেই এর উত্তর দিয়েছি।
ডিএমকেকে --- প্রাক্তন মডারেটর বিড়ালছানা

16

ব্যবহার করার জন্য hash, যেমন @lhunath প্রস্তাব দেওয়া , একটি ব্যাশ স্ক্রিপ্টের মধ্যে:

hash foo &> /dev/null
if [ $? -eq 1 ]; then
    echo >&2 "foo not found."
fi

এই স্ক্রিপ্টটি সঞ্চালিত হয় hashএবং তারপরে পরীক্ষিত হয় যে সর্বাধিক সাম্প্রতিক কমান্ডের প্রস্থান কোড, সঞ্চিত মানটি $?সমান কিনা 1। যদি hashখুঁজে না পাওয়া যায় fooতবে প্রস্থান কোড হবে 1। যদি fooউপস্থিত থাকে তবে প্রস্থান কোড হবে 0

&> /dev/nullপুননির্দেশনা মান ত্রুটি এবং মান আউটপুট থেকে hashযাতে এটি পর্দায় আসেন বলে মনে হচ্ছে না এবং echo >&2মান ত্রুটি বার্তা লিখেছেন।


8
শুধু কেন নয় if hash foo &> /dev/null; then ...?
বেনি চেরনিয়াভস্কি-পাসকিন

9

আমার যে বাক্সে অ্যাক্সেস রয়েছে তাতে কাজ করার জন্য পূর্ববর্তী উত্তরগুলি আমি কখনই পাইনি। একটির জন্য, typeইনস্টল করা হয়েছে (যা moreকরে তা করছে )। সুতরাং অন্তর্নির্মিত নির্দেশিকা প্রয়োজন। এই আদেশটি আমার পক্ষে কাজ করে:

if [ `builtin type -p vim` ]; then echo "TRUE"; else echo "FALSE"; fi

3
বন্ধনীগুলি ifসিনট্যাক্সের অংশ নয় , কেবল ব্যবহার করুন if builtin type -p vim; then ...। এবং ব্যাকটিকগুলি সত্যই প্রাচীন এবং অবচিত সিনট্যাক্স, $()এমনকি shসমস্ত আধুনিক সিস্টেমে সমর্থিত ।
nyuszika7h

9

একাধিক নির্ভরতা পরীক্ষা করুন এবং শেষ ব্যবহারকারীদের স্থিতি অবহিত করুন

for cmd in latex pandoc; do
  printf '%-10s' "$cmd"
  if hash "$cmd" 2>/dev/null; then
    echo OK
  else
    echo missing
  fi
done

নমুনা আউটপুট:

latex     OK
pandoc    missing

সমন্বয় করা 10সর্বাধিক কমান্ড দৈর্ঘ্যের সাথে । এটি স্বয়ংক্রিয় নয়, কারণ আমি এটি করার কোনও নন-ভারবসিক পসিক্স উপায় দেখতে পাচ্ছি না: আমি কীভাবে বাশে পৃথক স্থান পৃথক টেবিলের কলামগুলি বিন্যস্ত করতে পারি?

কিছু কিনা পরীক্ষা করে দেখুন apt প্যাকেজ ইনস্টল করা আছেdpkg -s এবং অন্যথায় সেগুলি ইনস্টল করুন

দেখা: কোনও এপট-প্যাকেজ ইনস্টল করা আছে কিনা তা পরীক্ষা করে এবং এটি লিনাক্সে না থাকলে ইনস্টল করুন

আগে এটি উল্লেখ করা হয়েছিল: বাশ স্ক্রিপ্ট থেকে কোনও প্রোগ্রাম উপস্থিত রয়েছে কিনা তা আমি কীভাবে পরীক্ষা করতে পারি?


1
এটি করার নন-ভারবজ উপায়: 1) প্রস্থ নির্দিষ্টকরণকারক থেকে মুক্তি পান; 2) আপনার কমান্ড নামের প্রিন্টফের পরে একটি স্থান যুক্ত করুন; 3) আপনার লুপের জন্য column -tইউপ-লিনাক্সের অংশটি পাইপ করুন ।
প্যাট্রিস লেভেস্ক

8

আপনি যদি প্রোগ্রামের অস্তিত্বের জন্য পরীক্ষা করেন, আপনি সম্ভবত পরে যাইহোক এটি চালাতে যাচ্ছেন। কেন এটি প্রথম স্থানে চালানোর চেষ্টা করবেন না?

if foo --version >/dev/null 2>&1; then
    echo Found
else
    echo Not found
fi

এটি আরও নির্ভরযোগ্য চেক যে প্রোগ্রামটি কেবলমাত্র PATH ডিরেক্টরিগুলি এবং ফাইল অনুমতিগুলির চেয়ে চেয়ে চালিত হয়।

এছাড়াও আপনি আপনার প্রোগ্রাম থেকে কিছু দরকারী ফলাফল পেতে পারেন যেমন এর সংস্করণ।

অবশ্যই ত্রুটিগুলি হ'ল কিছু প্রোগ্রাম শুরু করা ভারী হতে পারে এবং কিছুতে --versionঅবিলম্বে (এবং সফলভাবে) প্রস্থান করার বিকল্প নেই।


6

hash foo 2>/dev/null: জেড শেল (জেডএস), বাশ, ড্যাশ এবং অ্যাশ দিয়ে কাজ করে

type -p foo: এটি জেড শেল, বাশ এবং অ্যাশ ( ব্যাসিবক্স ) এর সাথে কাজ করে বলে মনে হচ্ছে তবে ড্যাশ নয় (এটি -pএকটি আর্গুমেন্ট হিসাবে ব্যাখ্যা করে )।

command -v foo: জেড শেল, বাশ, ড্যাশ দিয়ে কাজ করে তবে ছাই নয় (ব্যজিবক্স) ( -ash: command: not found)।

এছাড়াও খেয়াল করুন যে builtinছাই এবং ড্যাশ সহ উপলব্ধ নয়।


4

পারলে বাশ বিল্টিন ব্যবহার করুন:

which programname

...

type -P programname

15
তাই না? whichবাশ অন্তর্নির্মিত না।
ট্রিপল

টাইপ-পি প্রোগ্রামের নামটি অগ্রাধিকার দিতে হয়, গৃহীত উত্তর দেখুন
রবার্টজি

@ রবার্টজি আমি যা দেখছি তা পসিক্স -Pনয়। কেন type -Pপছন্দ হয়?
মাইকমেকানা

আমার এই বাক্যটি থাকা উচিত ছিল "বাশ পরিবেশে অগ্রাধিকার দেওয়া" - যেমন আমি বাশ-নির্দিষ্ট পূর্ববর্তী মন্তব্যের জবাব দেওয়ার পরিকল্পনা নিয়েছিলাম। যাইহোক, এটি বছর আগে ছিল - আমার ধারণা আমি ঠিক, আবারো আপনাকে "অভিযুক্ত" হিসাবে চিহ্নিত উত্তরটির দিকে নির্দেশ করব
রবার্টজি

4

-vPOSIX_BUILTINS বিকল্পটি এর জন্য সেট করা থাকলে কমান্ড সূক্ষ্মভাবে কাজ করে<command> পরীক্ষার জন্য তবে তা ব্যর্থ হতে পারে। (এটি আমার জন্য বছরের পর বছর ধরে কাজ করেছে, তবে আমি সম্প্রতি এমন এক জায়গায় গিয়েছিলাম যেখানে এটি কাজ করে না।)

আমি নিম্নলিখিতটি আরও ব্যর্থহীন বলে মনে করি:

test -x $(which <command>)

যেহেতু এটি তিনটি জিনিসের জন্য পরীক্ষা করে: পথ, অস্তিত্ব এবং সম্পাদনের অনুমতি।


কাজ করে না। test -x $(which ls)আয় 0, ঠিক যেমন test -x $(which sudo), যদিও lsইনস্টল করা থাকে এবং runnable এবং sudoএমনকি Docker ধারক আমি চলছি মধ্যে ইনস্টল করা নেই।
algal

@ অ্যালগাল আপনার মনে হয় উক্তিগুলি ব্যবহার করা দরকার, তাইtest -x "$(which <command>)"
JoniVR

@ এলগাল সম্ভবত lsএলিয়াস? কমান্ডের প্যারামিটার থাকলে এটি কাজ করবে বলে আমি মনে করি না।
অ্যান্থনিসি

3

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

dpkg --status libdb-dev | grep -q not-installed

if [ $? -eq 0 ]; then
    apt-get install libdb-dev
fi

আপনি উপরের দিক থেকে দেখতে পাচ্ছেন, ক্যোয়ারীর "0" উত্তরের অর্থ প্যাকেজ ইনস্টল করা নেই। এটি "গ্রেপ" এর একটি ফাংশন - একটি "0" অর্থ একটি মিল পাওয়া গেছে, একটি "1" এর অর্থ কোনও মিল পাওয়া যায় নি।


10
তবে, অ্যান্টি-প্যাটার্ন cmd; if [ $? -eq 0 ]; then এটিকে রিফ্যাক্ট করা উচিতif cmd; then
০৪ এ ট্রিপলি

এটি কেবলমাত্র মাধ্যমে ইনস্টল লিব জন্য কাজ করে dpkgবাapt
Weijun ঝু

3

এখানে প্রচুর বিকল্প রয়েছে, তবে আমি অবাক হয়েছি কোনও দ্রুত ও লাইনার নেই। আমি আমার স্ক্রিপ্টগুলির শুরুতে এটি ব্যবহার করেছি:

[[ "$(command -v mvn)" ]] || { echo "mvn is not installed" 1>&2 ; exit 1; }
[[ "$(command -v java)" ]] || { echo "java is not installed" 1>&2 ; exit 1; }

এটি এখানে নির্বাচিত উত্তর এবং অন্য উত্সের ভিত্তিতে তৈরি।


2

আমি বলব যে কোনও অসুস্থতার কারণে পোর্টেবল এবং 100% নির্ভরযোগ্য উপায় নেই alias। উদাহরণ স্বরূপ:

alias john='ls --color'
alias paul='george -F'
alias george='ls -h'
alias ringo=/

অবশ্যই, শুধুমাত্র শেষটি সমস্যাযুক্ত (রিঙ্গোর কোনও অপরাধ নয়!)। তবে এগুলির aliasসবগুলিই দৃষ্টিকোণ থেকে বৈধ এসএস command -v

মত ঝুঁকির বিষয়গুলি প্রত্যাখ্যান করতে ringo, আমাদের শেল বিল্ট-ইন aliasকমান্ডের আউটপুটটি পার্স করতে হবে এবং তাদের মধ্যে পুনরাবৃত্তি করতে হবে ( এখানে command -vউন্নত নয় alias) এটির জন্য কোনও বহনযোগ্য সমাধান নেই, এমনকি একটি বাশ- নির্দিষ্ট সমাধান বরং ক্লান্তিকর।

মনে রাখবেন যে এর মতো সমাধান নিঃশর্তভাবে প্রত্যাখ্যান করবে alias ls='ls -F':

test() { command -v $1 | grep -qv alias }

ভাল যুক্তি. যাইহোক, যখন কোনও ব্যাশ স্ক্রিপ্টের অভ্যন্তরীণ থেকে চালানো হয়, এলিয়াসগুলি দৃশ্যমান হয় না।
বেসিল মুসা

1
একটি সমস্যা আছে, কমান্ড 'ওরফে' পরীক্ষা করা হলে এটি মিথ্যা ফিরে আসবে। এটি সত্য ফিরে উচিত যখন। উদাহরণ: পরীক্ষা "ওরফে"
বাসিল মুসা

2
আমি কেবল পরীক্ষা করেছি এবং ব্যবহার shopt -u expand_aliasesকরে এই উপমাগুলি উপেক্ষা / লুকিয়ে রাখি এবং shopt -s expand_aliasesসেগুলি দিয়ে দেখায় command -v
ড্রাগন 788

1

whichকমান্ড সহায়ক হতে পারে।মানুষ যা

এক্সিকিউটেবল পাওয়া গেলে এটি 0 প্রদান করে এবং যদি এটি কার্যকর না হয় বা কার্যকর না হয় তবে 1 প্রদান করে:

NAME

       which - locate a command

SYNOPSIS

       which [-a] filename ...

DESCRIPTION

       which returns the pathnames of the files which would
       be executed in the current environment, had its
       arguments been given as commands in a strictly
       POSIX-conformant shell. It does this by searching
       the PATH for executable files matching the names
       of the arguments.

OPTIONS

       -a     print all matching pathnames of each argument

EXIT STATUS

       0      if all specified commands are 
              found and executable

       1      if one or more specified commands is nonexistent
              or not executable

       2      if an invalid option is specified

খুব সুন্দর বিষয়টি whichহ'ল এটি নির্ধারণ করে যে পরিবেশটি whichচালু পরিবেশে কার্যকর করা যায় কিনা - এটি কয়েকটি সমস্যা বাঁচায় ...


আপনি যদি কোনও এক্সিকিউটেবল নামের নামের সন্ধান করেন তবে এটি ব্যবহার করুন, তবে আপনি যদি কোনও নির্দিষ্ট ফাইল / পাথ / টু / এ / নাম / ফু পরীক্ষা করতে চান তবে আমার উত্তরটি দেখুন। এছাড়াও নোট করুন যা কিছু ন্যূনতম সিস্টেমে উপলভ্য নয়, যদিও এটি কোনও পূর্ণাঙ্গ ইনস্টলেশনতে উপস্থিত থাকতে হবে ...
ডিএমকেকে --- প্রাক্তন মডারেটর বিড়ালছানা

9
কোনটির প্রস্থান স্থিতিতে নির্ভর করবেন না। অনেক অপারেটিং সিস্টেমে এমন একটি রয়েছে যা 0 এর
বাইরেও

1

একটি ডেবিয়ান সার্ভারের জন্য আমার সেটআপ :

একাধিক প্যাকেজগুলিতে একই নাম থাকা অবস্থায় আমার সমস্যা ছিল।

উদাহরণস্বরূপ apache2। সুতরাং এটি আমার সমাধান ছিল:

function _apt_install() {
    apt-get install -y $1 > /dev/null
}

function _apt_install_norecommends() {
    apt-get install -y --no-install-recommends $1 > /dev/null
}
function _apt_available() {
    if [ `apt-cache search $1 | grep -o "$1" | uniq | wc -l` = "1" ]; then
        echo "Package is available : $1"
        PACKAGE_INSTALL="1"
    else
        echo "Package $1 is NOT available for install"
        echo  "We can not continue without this package..."
        echo  "Exitting now.."
        exit 0
    fi
}
function _package_install {
    _apt_available $1
    if [ "${PACKAGE_INSTALL}" = "1" ]; then
        if [ "$(dpkg-query -l $1 | tail -n1 | cut -c1-2)" = "ii" ]; then
             echo  "package is already_installed: $1"
        else
            echo  "installing package : $1, please wait.."
            _apt_install $1
            sleep 0.5
        fi
    fi
}

function _package_install_no_recommends {
    _apt_available $1
    if [ "${PACKAGE_INSTALL}" = "1" ]; then
        if [ "$(dpkg-query -l $1 | tail -n1 | cut -c1-2)" = "ii" ]; then
             echo  "package is already_installed: $1"
        else
            echo  "installing package : $1, please wait.."
            _apt_install_norecommends $1
            sleep 0.5
        fi
    fi
}

1

আপনি যদি ছেলেরা / গালগুলি এখানে কাজের উত্তরের জিনিসগুলি পেতে না পারেন এবং আপনার পিছন থেকে চুল টানছেন, তবে একই কমান্ডটি ব্যবহার করে চালানোর চেষ্টা করুন bash -c। এই দৃষ্টিনন্দন প্রলাপ দেখুন। আপনি run (সাব-কমান্ড) চালানোর সময় সত্যই এটি ঘটছে:

প্রথম। এটি আপনাকে সম্পূর্ণ আলাদা আউটপুট দিতে পারে।

$ command -v ls
alias ls='ls --color=auto'
$ bash -c "command -v ls"
/bin/ls

দ্বিতীয়ত। এটি আপনাকে কোনও আউটপুট দিতে পারে না।

$ command -v nvm
nvm
$ bash -c "command -v nvm"
$ bash -c "nvm --help"
bash: nvm: command not found

শেলটির ইন্টারেক্টিভ এবং অ-ইন্টারেক্টিভ মোডের মধ্যে পার্থক্যের কারণে পার্থক্যগুলি ঘটে। আপনার ~ / .bashrc কেবল তখনই পঠিত হয় যখন শেলটি অ-লগইন এবং ইন্টারেক্টিভ হয়। দ্বিতীয়টি যদিও দেখতে অদ্ভুত দেখাচ্ছে কারণ এটি অবশ্যই প্যাথ পরিবেশের পরিবর্তনশীলের পার্থক্যের কারণে হওয়া উচিত তবে সাবসেলগুলি পরিবেশের উত্তরাধিকারী।
প্লেক

আমার ক্ষেত্রে .bashrcএকটি [ -z "$PS1" ] && returnপ্রেন্ডেন্ড রয়েছে # If not running interactively, don't do anythingতাই আমি অনুমান করি যে এটি কারণ হ'ল এমনকি অ ইন্টারেক্টিভ মোডে বাষার্কের সুস্পষ্ট উত্সাহও সহায়তা করে না। Ss64.com/bash/source.html ডট অপারেটরের সাথে স্ক্রিপ্ট কল করে সমস্যাটির সমাধান করা যেতে পারে . ./script.shতবে এটি প্রতিবার টাইপ করা মনে রাখার মতো জিনিস নয়।
ব্যবহারকারী 619271

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

যদি এটি ব্যাখ্যা করে যে এই ক্ষেত্রে কী চলছে, তবে এটি কোনও উত্তরের সহায়ক সহায়ক হবে।
প্লেলে

1

এটি প্রোগ্রাম অনুসারে বা না থাকলে অবস্থান অনুযায়ী জানায়:

    if [ -x /usr/bin/yum ]; then
        echo "This is Centos"
    fi

হ্যাঁ আমি এই কমান্ডটি যুক্ত করেছি যদি আপনার সেভেরারে কোনও প্যাকেজ ইনস্টল করার প্রয়োজন হয়, ওপেন সুস, সেন্টোস, দেবিয়ান
ক্লিভিন কোনা

সিনোট্যাক্স হাইলাইটিংটি "প্রতিধ্বনি" লাইনে বন্ধ রয়েছে। সমাধান কি? এটি কি বাশ স্ক্রিপ্টটি আলাদা হওয়া উচিত বলে পরামর্শ দেয়?
পিটার মর্টেনসেন

@ পিটারমোরটেনসেন সিনট্যাক্স হাইলাইটিং বন্ধ আছে কারণ এটি এটি একটি স্ট্রিংকে চিনতে পারে না।
অ্যাড্রিয়েন

0

হ্যাশ-বৈকল্পিকের একটি ক্ষতি রয়েছে: কমান্ড লাইনে আপনি উদাহরণস্বরূপ টাইপ করতে পারেন

one_folder/process

প্রক্রিয়া কার্যকর করা। এর জন্য ওয়ান_ফোল্ডারের মূল ফোল্ডারটি অবশ্যই $ PATH এ থাকতে হবে । তবে আপনি যখন এই আদেশটি হ্যাশ করার চেষ্টা করবেন, এটি সর্বদা সফল হবে:

hash one_folder/process; echo $? # will always output '0'

4
"এটির জন্য ওয়ান_ফোল্ডারের পিতা-মাতা ফোল্ডারটি অবশ্যই $PATH" "এটি সম্পূর্ণরূপে ভুল c চেষ্টা করে দেখুন এটি কাজ করার জন্য, ওয়ানফোল্ডারটি বর্তমান ডিরেক্টরিতে থাকতে হবে ।
ওয়াইল্ডকার্ড

0

আমি "কমান্ড-ভি" ব্যবহারের পরে দ্বিতীয়। যেমন:

md=$(command -v mkdirhier) ; alias md=${md:=mkdir}  # bash

emacs="$(command -v emacs) -nw" || emacs=nano
alias e=$emacs
[[ -z $(command -v jed) ]] && alias jed=$emacs

0

আমাদের সিআই সার্ভার স্থাপনের অংশ হিসাবে গিটটি ইনস্টল করা হয়েছে কিনা তা আমাকে পরীক্ষা করে দেখতে হয়েছিল । আমার চূড়ান্ত বাশ স্ক্রিপ্টটি নিম্নরূপ ছিল (উবুন্টু সার্ভার):

if ! builtin type -p git &>/dev/null; then
  sudo apt-get -y install git-core
fi

3
শর্তসাপেক্ষটি বরং অকেজো, অ্যাপ্ট-গেটটি চালুর জন্য স্টার্টআপের সময়টি মডুলো করে, যেমন অ্যাপ্লিকেশনটি সন্তুষ্ট হবে এবং গিট-কোর ইতিমধ্যে ইনস্টল করা থাকলে প্রস্থান করবে।
ট্রিপলি

3
এটির প্রারম্ভকালীন সময়টি উপেক্ষণীয় নয়, তবে আরও গুরুত্বপূর্ণ অনুপ্রেরণা হ'ল sudo: শর্ত ছাড়াই এটি সর্বদা বন্ধ হয়ে পাসওয়ার্ডের জন্য জিজ্ঞাসা করে (যদি আপনি সম্প্রতি একটি সুডো না করেন)। বিটিডাব্লু, sudo -p "Type your password to install missing git-core: "প্রম্পটটি নীল থেকে বেরিয়ে আসে তাই এটি করা কার্যকর হতে পারে ।
বেনি চেরনিয়াভস্কি-পাসকিন

0

বাশের নকল type -P cmdকরতে, আমরা পসিক্স অনুবর্তী ব্যবহার করতে পারি env -i type cmd 1>/dev/null 2>&1

man env
# "The option '-i' causes env to completely ignore the environment it inherits."
# In other words, there are no aliases or functions to be looked up by the type command.

ls() { echo 'Hello, world!'; }

ls
type ls
env -i type ls

cmd=ls
cmd=lsx
env -i type $cmd 1>/dev/null 2>&1 || { echo "$cmd not found"; exit 1; }

7
কেন এটি উপবিষ্টিত হচ্ছে? কোন সিস্টেমে এটি আপনার পক্ষে কাজ করে? typeএকটি মনে করা হয় builtinসবচেয়ে শাঁস যাতে এই কারণে কাজ করতে পারছে না envব্যবহারসমূহ execvpচালানোর জন্য command, যাতে commandনা হতে পারে builtin(এবং builtinসবসময় একই পরিবেশের মধ্যে চালানো হবে)। এটি আমার জন্য ব্যর্থ মধ্যে bash, ksh93, zsh, busybox [a]shএবং dashযার সব প্রদান typeশেল builtin হিসাবে।
অ্যাড্রিয়ান ফ্রহ্বর্থ

0

যদি কোনও বাহ্যিক typeকমান্ড উপলভ্য না হয় (যেমনটি এখানে দেওয়া হয়েছে ), আমরা পসিক্স অনুগত ব্যবহার করতে পারি env -i sh -c 'type cmd 1>/dev/null 2>&1':

# Portable version of Bash's type -P cmd (without output on stdout)
typep() {
   command -p env -i PATH="$PATH" sh -c '
      export LC_ALL=C LANG=C
      cmd="$1"
      cmd="`type "$cmd" 2>/dev/null || { echo "error: command $cmd not found; exiting ..." 1>&2; exit 1; }`"
      [ $? != 0 ] && exit 1
      case "$cmd" in
        *\ /*) exit 0;;
            *) printf "%s\n" "error: $cmd" 1>&2; exit 1;;
      esac
   ' _ "$1" || exit 1
}

# Get your standard $PATH value
#PATH="$(command -p getconf PATH)"
typep ls
typep builtin
typep ls-temp

কমপক্ষে ম্যাক ওএস এক্স ভি ১০. ..৮ (স্নো চিতাবাঘ) এ ব্যাশ ৪.২.২৪ (২) ব্যবহার করা কোনও মুদ্রার সাথে command -v lsমেলে না /bin/ls-temp


0

আপনি যদি কোনও প্রোগ্রামের উপস্থিতি এবং সত্যই কোনও প্রোগ্রাম কিনা তা পরীক্ষা করতে চান তবে কোনও বাশ অন্তর্নির্মিত কমান্ড নয়command , typeএবং তারপরhash হয় না তারা আদেশগুলিতে তৈরি-জন্য সব রিটার্ন 0 প্রস্থান অবস্থা পরীক্ষার জন্য যথাযথ।

উদাহরণস্বরূপ, এমন সময় প্রোগ্রাম রয়েছে যা সময় অন্তর্নির্মিত কমান্ডের চেয়ে বেশি বৈশিষ্ট্য সরবরাহ করে । প্রোগ্রামটি বিদ্যমান কিনা তা পরীক্ষা করতে, আমি whichনিম্নলিখিত উদাহরণ হিসাবে ব্যবহার করার পরামর্শ দিচ্ছি :

# First check if the time program exists
timeProg=`which time`
if [ "$timeProg" = "" ]
then
  echo "The time program does not exist on this system."
  exit 1
fi

# Invoke the time program
$timeProg --quiet -o result.txt -f "%S %U + p" du -sk ~
echo "Total CPU time: `dc -f result.txt` seconds"
rm result.txt

-1

লিপি

#!/bin/bash

# Commands found in the hash table are checked for existence before being
# executed and non-existence forces a normal PATH search.
shopt -s checkhash

function exists() {
 local mycomm=$1; shift || return 1

 hash $mycomm 2>/dev/null || \
 printf "\xe2\x9c\x98 [ABRT]: $mycomm: command does not exist\n"; return 1;
}
readonly -f exists

exists notacmd
exists bash
hash
bash -c 'printf "Fin.\n"'

ফলাফল

 [ABRT]: notacmd: command does not exist
hits    command
   0    /usr/bin/bash
Fin.

-1

আমি এটি ব্যবহার করি, কারণ এটি খুব সহজ:

if [ `LANG=C type example 2>/dev/null|wc -l` = 1 ];then echo exists;else echo "not exists";fi

অথবা

if [ `LANG=C type example 2>/dev/null|wc -l` = 1 ];then
echo exists
else echo "not exists"
fi

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


-1

ধরে নিচ্ছি আপনি ইতিমধ্যে নিরাপদ শেল অভ্যাস অনুসরণ করছেন :

set -eu -o pipefail
shopt -s failglob

./dummy --version 2>&1 >/dev/null

এটি ধরে নিয়েছে যে কমান্ডটি এমনভাবে আহ্বান করা যেতে পারে যা এটি (প্রায়) কিছুই করে না, যেমন এর সংস্করণটি প্রতিবেদন করা বা সহায়তা দেখানো।

যদি dummyকমান্ডটি খুঁজে পাওয়া যায় না, তবে নীচের ত্রুটিটি সহ বাশ প্রস্থান করে ...

./my-script: line 8: dummy: command not found

এটি অন্যান্য command -v(এবং অনুরূপ) উত্তরের চেয়ে আরও কার্যকর এবং কম ভার্বোজ কারণ ত্রুটি বার্তাটি স্বয়ংক্রিয়ভাবে উত্পন্ন হয় এবং এতে একটি প্রাসঙ্গিক লাইন নম্বর থাকে।


যারা শেল দিয়ে ভাল নয় তাদের পক্ষে এই উত্তরটি খুব স্পষ্ট নয় কারণ এটি এই কোডটি কীভাবে ব্যবহার করার কথা বলে তা বর্ণনা করে না এবং এটি অন্য অনেক উত্তর থেকে পৃথক হয় যে dummyঅস্তিত্বের জন্য পরীক্ষার ব্যর্থ শাখাটি হাতছাড়া হয়ে যায় স্ক্রিপ্ট এর লেখক। এছাড়াও, এটি কীভাবে কাজ করে এবং এটি কার্যকর করার পরিবেশের সেটিংস পরিবর্তন করে তার ব্যাখ্যা নেই cks
প্লেক

এটি বাশ প্রশ্ন, তবে এটি উল্লেখযোগ্য যে নন-পসিক্স shoptকলটি পসিক্সের সাথে প্রতিস্থাপন করা যেতে পারে set -f, যা সংক্ষিপ্ত এবং বহনযোগ্য। Pipefail বিকল্প POSIX সমর্থিত না , যদিও, এবং কোন বিকল্প আমি যতদূর জানি হয়।
প্যালেক

@ প্যালেক আমি নিশ্চিত না যে এটি কীভাবে কঠিন। এটি শালটির উপর নির্ভর করে এটি ওপেন দ্বারা অনুরোধ অনুসারে, কমান্ডটি খুঁজে পাওয়া যায় না এবং কোনও ত্রুটি সহ প্রস্থান করে user আমাকে কী মিস করলাম তা আমাকে
অ্যাড্রিয়েন
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.