আমি কীভাবে কোনও প্রোগ্রামের উপস্থিতি যাচাই করব যে এমনভাবে কোনও ত্রুটি ফিরে আসবে এবং প্রস্থান করবে বা স্ক্রিপ্টটি দিয়ে চালিয়ে যাবে?
মনে হয় এটি সহজ হওয়া উচিত, তবে এটি আমাকে স্টাম্পিং করে চলেছে।
আমি কীভাবে কোনও প্রোগ্রামের উপস্থিতি যাচাই করব যে এমনভাবে কোনও ত্রুটি ফিরে আসবে এবং প্রস্থান করবে বা স্ক্রিপ্টটি দিয়ে চালিয়ে যাবে?
মনে হয় এটি সহজ হওয়া উচিত, তবে এটি আমাকে স্টাম্পিং করে চলেছে।
উত্তর:
পসিক্স সামঞ্জস্যপূর্ণ:
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
}
2>&- ("ক্লোজ আউটপুট ফাইল ডেস্ক্রিপ্টর 2", যা স্ট্যাডার) এর একই ফলাফল রয়েছে 2> /dev/null; 2) >&2হ'ল একটি শর্টকাট 1>&2, যা আপনি "স্টাডারকে স্টার্ডারে পুনর্নির্দেশ" হিসাবে স্বীকৃতি দিতে পারেন। আরও তথ্যের জন্য উন্নত বাশ স্ক্রিপ্টিং গাইড i / o পুনঃনির্দেশ পৃষ্ঠাটি দেখুন।
while read element ; do .. done <<< $(echo ${ArrayVar[*]}), for word in $(fgrep -l $ORIGINAL *.txt), ls -l "$directory" | sed 1d , {{জন্য একটি seq $BEGIN $END}}, ... বহু লেখক সঙ্গে যোগাযোগ করুন এবং উন্নতি উত্থাপন করা চেষ্টা করেছি কিন্তু এটা কোন উইকি এবং অনুরোধ বধির কান অবতরণ করেছে।
2>&-হয় না হিসাবে একই 2>/dev/null। প্রাক্তন ফাইল বর্ণনাকারী বন্ধ করে দেয়, তবে পরেরটি কেবল এটিকে পুনর্নির্দেশ করে /dev/null। আপনি কোনও ত্রুটি দেখতে পাবেন না কারণ প্রোগ্রামটি আপনাকে স্ট্যাডারে আপনাকে জানানোর চেষ্টা করে যে স্ট্যাডার বন্ধ রয়েছে।
কমান্ডের উপস্থিতি রয়েছে $PATH এবং তা কার্যকরযোগ্য কিনা তা যাচাই করার জন্য নিম্নলিখিতটি একটি পোর্টেবল উপায় :
[ -x "$(command -v foo)" ]
উদাহরণ:
if ! [ -x "$(command -v git)" ]; then
echo 'Error: git is not installed.' >&2
exit 1
fi
এক্সিকিউটেবল চেক প্রয়োজন কারণ ব্যাশ একটি অ-এক্সিকিউটেবল ফাইল ফিরিয়ে দেয় যদি সেই নামের সাথে কোনও এক্সিকিউটেবল ফাইল না পাওয়া যায় $PATH।
এছাড়াও মনে রাখবেন যে এক্সিকিউটেবলের একই নামযুক্ত কোনও অ-এক্সিকিউটেবল ফাইল যদি আগে বিদ্যমান থাকে তবে $PATHড্যাশ পূর্বেরটিকে কার্যকর করে দেয়, যদিও পরবর্তীটি কার্যকর করা হত। এটি একটি ত্রুটি এবং POSIX মান লঙ্ঘন করছে। [ বাগ রিপোর্ট ] [ মানক ]
এছাড়াও, আপনি যে কমান্ডটির সন্ধান করছেন সেটি একটি উপাধিকার হিসাবে সংজ্ঞায়িত করা থাকলে এটি ব্যর্থ হবে।
command -vঅ-এক্সিকিউটেবল ফাইলের জন্যও কোনও পথ তৈরি করবে ? যে, -x সত্যিই প্রয়োজনীয়?
-xপরীক্ষা করে দেখায় যে ফাইলটি কার্যকর হয়, যা প্রশ্নটি ছিল।
commandএটি নিজে কার্যকর করার জন্য পরীক্ষা করবে - তাই না?
$PATHকোনও কমান্ড কার্যকর করার সময় ড্যাশ, ব্যাশ এবং জ্যাশ সমস্ত অ-এক্সিকিউটেবল ফাইলের বাইরে যান । তবে এর আচরণটি command -vঅত্যন্ত বেমানান। ড্যাশ এ, এটি নির্বাহযোগ্য $PATHকিনা তা নির্বিশেষে এটি প্রথম মেলানো ফাইলটি ফেরত দেয় । ব্যাশে এটি প্রথম সম্পাদনযোগ্য ম্যাচটি ফেরত দেয় $PATH, তবে যদি কিছুই না থাকে তবে এটি একটি এক্সিকিউটেবল ফাইলটি ফিরিয়ে দিতে পারে। এবং zsh এ এটি কখনই কোনও এক্সিকিউটেবল ফাইল ফিরিয়ে দেবে না।
dashএই তিনটির মধ্যে কেবলমাত্র একজনই যে নন-পসিক্স-সম্মতিযুক্ত; [ -x "$(command -v COMMANDNAME)"]অন্য দুটিতে কাজ করবে। দেখে মনে হচ্ছে এই বাগটি ইতিমধ্যে প্রতিবেদন করা হয়েছে তবে এখনও তার কোনও প্রতিক্রিয়া পাওয়া যায় নি: bugs.debian.org/cgi-bin/bugreport.cgi?bug=874264
আমি লুনাথের ব্যবহারকে নিরুৎসাহিত করার সাথে একমত 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তা নয়।
exit 1;সেখান থেকে আহবান করা হলে একটি এক্সটার্ম মেরে ফেলে।
&>/dev/null। যাইহোক, আমি আপনার সাথে একমত হইলাম, যা যা সত্যই গুরুত্বপূর্ণ তা বহনযোগ্যতা, আমি সেই অনুসারে আমার উত্তর সম্পাদনা করেছি, এখন স্ট্যান্ডার্ড শ রিডাইরেক্ট ব্যবহার করে >/dev/null 2>&1।
আমার .bashrc এ একটি ফাংশন সংজ্ঞায়িত করা হয়েছে যা এটি আরও সহজ করে তোলে।
command_exists () {
type "$1" &> /dev/null ;
}
এটি কীভাবে ব্যবহৃত হয় তার একটি উদাহরণ এখানে রয়েছে (আমার কাছ থেকে .bash_profile)
if command_exists mvim ; then
export VISUAL="mvim --nofork"
fi
&>?
&> উভয় stdout- এ এবং দ্বারা stderr পুননির্দেশনা একসঙ্গে।
&>আপনার বাশের সংস্করণে উপলভ্য নাও হতে পারে। মার্সেলো কোড ভাল কাজ করা উচিত; এটি একই জিনিস করে।
thenউদাহরণ দিয়ে শব্দটি দিয়ে এটি ব্যবহার করে দেখুন। আপনার যদি নির্বাহের অস্তিত্বের প্রয়োজন হয় তবে এই উত্তরটি দেখুন $PATH।
এটি $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প্রোগ্রামটির আউটপুটকে দমন করে ।
@ লুনাথ এবং @ গ্রেগভির উত্তরগুলিতে প্রসারিত করে, এখানে এমন লোকদের কোড যা এই 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
commandএমনকি এলিয়াসগুলির ক্ষেত্রেও সফল হয় , যা কিছুটা বিপরীত হতে পারে। একটি ইন্টারেক্টিভ শেলটিতে অস্তিত্বের জন্য অনুসন্ধান করা যখন আপনি এটি কোনও স্ক্রিপ্টে স্থানান্তরিত করেন তখন থেকে আলাদা ফলাফল দেওয়া হবে।
shopt -u expand_aliasesউপেক্ষা উপেক্ষা / লুকিয়ে রাখি ( alias ls='ls -F'অন্য উত্তরে উল্লিখিত মত ) এবং এর shopt -s expand_aliasesমাধ্যমে তাদের সমাধান করেছি command -v। সুতরাং সম্ভবত এটি চেকের আগে সেট করা উচিত এবং পরে আনসেট করা উচিত, যদিও এটি ফাংশন রিটার্ন মানকে প্রভাবিত করতে পারে যদি আপনি কমান্ড কলের আউটপুটকে স্পষ্টভাবে ক্যাপচার না করে এবং ফিরিয়ে না দেন।
ব্যবহার করার চেষ্টা করুন:
test -x filename
অথবা
[ -x filename ]
শর্তাধীন অভিব্যক্তিগুলির অধীনে বাশ ম্যানপেজ থেকে :
-x file True if file exists and is executable.
ব্যবহার করার জন্য 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মান ত্রুটি বার্তা লিখেছেন।
if hash foo &> /dev/null; then ...?
আমার যে বাক্সে অ্যাক্সেস রয়েছে তাতে কাজ করার জন্য পূর্ববর্তী উত্তরগুলি আমি কখনই পাইনি। একটির জন্য, typeইনস্টল করা হয়েছে (যা moreকরে তা করছে )। সুতরাং অন্তর্নির্মিত নির্দেশিকা প্রয়োজন। এই আদেশটি আমার পক্ষে কাজ করে:
if [ `builtin type -p vim` ]; then echo "TRUE"; else echo "FALSE"; fi
ifসিনট্যাক্সের অংশ নয় , কেবল ব্যবহার করুন if builtin type -p vim; then ...। এবং ব্যাকটিকগুলি সত্যই প্রাচীন এবং অবচিত সিনট্যাক্স, $()এমনকি shসমস্ত আধুনিক সিস্টেমে সমর্থিত ।
একাধিক নির্ভরতা পরীক্ষা করুন এবং শেষ ব্যবহারকারীদের স্থিতি অবহিত করুন
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 এবং অন্যথায় সেগুলি ইনস্টল করুন ।
দেখা: কোনও এপট-প্যাকেজ ইনস্টল করা আছে কিনা তা পরীক্ষা করে এবং এটি লিনাক্সে না থাকলে ইনস্টল করুন
আগে এটি উল্লেখ করা হয়েছিল: বাশ স্ক্রিপ্ট থেকে কোনও প্রোগ্রাম উপস্থিত রয়েছে কিনা তা আমি কীভাবে পরীক্ষা করতে পারি?
column -tইউপ-লিনাক্সের অংশটি পাইপ করুন ।
আপনি যদি প্রোগ্রামের অস্তিত্বের জন্য পরীক্ষা করেন, আপনি সম্ভবত পরে যাইহোক এটি চালাতে যাচ্ছেন। কেন এটি প্রথম স্থানে চালানোর চেষ্টা করবেন না?
if foo --version >/dev/null 2>&1; then
echo Found
else
echo Not found
fi
এটি আরও নির্ভরযোগ্য চেক যে প্রোগ্রামটি কেবলমাত্র PATH ডিরেক্টরিগুলি এবং ফাইল অনুমতিগুলির চেয়ে চেয়ে চালিত হয়।
এছাড়াও আপনি আপনার প্রোগ্রাম থেকে কিছু দরকারী ফলাফল পেতে পারেন যেমন এর সংস্করণ।
অবশ্যই ত্রুটিগুলি হ'ল কিছু প্রোগ্রাম শুরু করা ভারী হতে পারে এবং কিছুতে --versionঅবিলম্বে (এবং সফলভাবে) প্রস্থান করার বিকল্প নেই।
hash foo 2>/dev/null: জেড শেল (জেডএস), বাশ, ড্যাশ এবং অ্যাশ দিয়ে কাজ করে ।
type -p foo: এটি জেড শেল, বাশ এবং অ্যাশ ( ব্যাসিবক্স ) এর সাথে কাজ করে বলে মনে হচ্ছে তবে ড্যাশ নয় (এটি -pএকটি আর্গুমেন্ট হিসাবে ব্যাখ্যা করে )।
command -v foo: জেড শেল, বাশ, ড্যাশ দিয়ে কাজ করে তবে ছাই নয় (ব্যজিবক্স) ( -ash: command: not found)।
এছাড়াও খেয়াল করুন যে builtinছাই এবং ড্যাশ সহ উপলব্ধ নয়।
পারলে বাশ বিল্টিন ব্যবহার করুন:
which programname
...
type -P programname
whichবাশ অন্তর্নির্মিত না।
-Pনয়। কেন type -Pপছন্দ হয়?
-vPOSIX_BUILTINS বিকল্পটি এর জন্য সেট করা থাকলে কমান্ড সূক্ষ্মভাবে কাজ করে<command> পরীক্ষার জন্য তবে তা ব্যর্থ হতে পারে। (এটি আমার জন্য বছরের পর বছর ধরে কাজ করেছে, তবে আমি সম্প্রতি এমন এক জায়গায় গিয়েছিলাম যেখানে এটি কাজ করে না।)
আমি নিম্নলিখিতটি আরও ব্যর্থহীন বলে মনে করি:
test -x $(which <command>)
যেহেতু এটি তিনটি জিনিসের জন্য পরীক্ষা করে: পথ, অস্তিত্ব এবং সম্পাদনের অনুমতি।
test -x $(which ls)আয় 0, ঠিক যেমন test -x $(which sudo), যদিও lsইনস্টল করা থাকে এবং runnable এবং sudoএমনকি Docker ধারক আমি চলছি মধ্যে ইনস্টল করা নেই।
test -x "$(which <command>)"
lsএলিয়াস? কমান্ডের প্যারামিটার থাকলে এটি কাজ করবে বলে আমি মনে করি না।
আগ্রহীদের জন্য, আপনি যদি কোনও ইনস্টলড লাইব্রেরি সনাক্ত করতে চান তবে পূর্বের উত্তরের কোনও পদ্ধতিই কাজ করে না। আমি ভাবছি আপনি শারীরিকভাবে পথটি পরীক্ষা করতে পারবেন (সম্ভাব্যভাবে শিরোলেখ ফাইল এবং এর জন্য), বা এর মতো কিছু (যদি আপনি ডেবিয়ান-ভিত্তিক বিতরণে থাকেন):
dpkg --status libdb-dev | grep -q not-installed
if [ $? -eq 0 ]; then
apt-get install libdb-dev
fi
আপনি উপরের দিক থেকে দেখতে পাচ্ছেন, ক্যোয়ারীর "0" উত্তরের অর্থ প্যাকেজ ইনস্টল করা নেই। এটি "গ্রেপ" এর একটি ফাংশন - একটি "0" অর্থ একটি মিল পাওয়া গেছে, একটি "1" এর অর্থ কোনও মিল পাওয়া যায় নি।
cmd; if [ $? -eq 0 ]; then এটিকে রিফ্যাক্ট করা উচিতif cmd; then
dpkgবাapt
এখানে প্রচুর বিকল্প রয়েছে, তবে আমি অবাক হয়েছি কোনও দ্রুত ও লাইনার নেই। আমি আমার স্ক্রিপ্টগুলির শুরুতে এটি ব্যবহার করেছি:
[[ "$(command -v mvn)" ]] || { echo "mvn is not installed" 1>&2 ; exit 1; }
[[ "$(command -v java)" ]] || { echo "java is not installed" 1>&2 ; exit 1; }
এটি এখানে নির্বাচিত উত্তর এবং অন্য উত্সের ভিত্তিতে তৈরি।
আমি বলব যে কোনও অসুস্থতার কারণে পোর্টেবল এবং 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 }
shopt -u expand_aliasesকরে এই উপমাগুলি উপেক্ষা / লুকিয়ে রাখি এবং shopt -s expand_aliasesসেগুলি দিয়ে দেখায় command -v।
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চালু পরিবেশে কার্যকর করা যায় কিনা - এটি কয়েকটি সমস্যা বাঁচায় ...
একটি ডেবিয়ান সার্ভারের জন্য আমার সেটআপ :
একাধিক প্যাকেজগুলিতে একই নাম থাকা অবস্থায় আমার সমস্যা ছিল।
উদাহরণস্বরূপ 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
}
আপনি যদি ছেলেরা / গালগুলি এখানে কাজের উত্তরের জিনিসগুলি পেতে না পারেন এবং আপনার পিছন থেকে চুল টানছেন, তবে একই কমান্ডটি ব্যবহার করে চালানোর চেষ্টা করুন 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একটি [ -z "$PS1" ] && returnপ্রেন্ডেন্ড রয়েছে # If not running interactively, don't do anythingতাই আমি অনুমান করি যে এটি কারণ হ'ল এমনকি অ ইন্টারেক্টিভ মোডে বাষার্কের সুস্পষ্ট উত্সাহও সহায়তা করে না। Ss64.com/bash/source.html ডট অপারেটরের সাথে স্ক্রিপ্ট কল করে সমস্যাটির সমাধান করা যেতে পারে . ./script.shতবে এটি প্রতিবার টাইপ করা মনে রাখার মতো জিনিস নয়।
এটি প্রোগ্রাম অনুসারে বা না থাকলে অবস্থান অনুযায়ী জানায়:
if [ -x /usr/bin/yum ]; then
echo "This is Centos"
fi
হ্যাশ-বৈকল্পিকের একটি ক্ষতি রয়েছে: কমান্ড লাইনে আপনি উদাহরণস্বরূপ টাইপ করতে পারেন
one_folder/process
প্রক্রিয়া কার্যকর করা। এর জন্য ওয়ান_ফোল্ডারের মূল ফোল্ডারটি অবশ্যই $ PATH এ থাকতে হবে । তবে আপনি যখন এই আদেশটি হ্যাশ করার চেষ্টা করবেন, এটি সর্বদা সফল হবে:
hash one_folder/process; echo $? # will always output '0'
$PATH" "এটি সম্পূর্ণরূপে ভুল c চেষ্টা করে দেখুন এটি কাজ করার জন্য, ওয়ানফোল্ডারটি বর্তমান ডিরেক্টরিতে থাকতে হবে ।
আমি "কমান্ড-ভি" ব্যবহারের পরে দ্বিতীয়। যেমন:
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
আমাদের সিআই সার্ভার স্থাপনের অংশ হিসাবে গিটটি ইনস্টল করা হয়েছে কিনা তা আমাকে পরীক্ষা করে দেখতে হয়েছিল । আমার চূড়ান্ত বাশ স্ক্রিপ্টটি নিম্নরূপ ছিল (উবুন্টু সার্ভার):
if ! builtin type -p git &>/dev/null; then
sudo apt-get -y install git-core
fi
sudo: শর্ত ছাড়াই এটি সর্বদা বন্ধ হয়ে পাসওয়ার্ডের জন্য জিজ্ঞাসা করে (যদি আপনি সম্প্রতি একটি সুডো না করেন)। বিটিডাব্লু, sudo -p "Type your password to install missing git-core: "প্রম্পটটি নীল থেকে বেরিয়ে আসে তাই এটি করা কার্যকর হতে পারে ।
বাশের নকল 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; }
typeএকটি মনে করা হয় builtinসবচেয়ে শাঁস যাতে এই কারণে কাজ করতে পারছে না envব্যবহারসমূহ execvpচালানোর জন্য command, যাতে commandনা হতে পারে builtin(এবং builtinসবসময় একই পরিবেশের মধ্যে চালানো হবে)। এটি আমার জন্য ব্যর্থ মধ্যে bash, ksh93, zsh, busybox [a]shএবং dashযার সব প্রদান typeশেল builtin হিসাবে।
যদি কোনও বাহ্যিক 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।
আপনি যদি কোনও প্রোগ্রামের উপস্থিতি এবং সত্যই কোনও প্রোগ্রাম কিনা তা পরীক্ষা করতে চান তবে কোনও বাশ অন্তর্নির্মিত কমান্ড নয়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
লিপি
#!/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.
আমি এটি ব্যবহার করি, কারণ এটি খুব সহজ:
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
এটি স্ট্যান্ডার্ড আউটপুটে শেল বিল্টিনস এবং প্রোগ্রামগুলির প্রতিধ্বনি স্থিতি ব্যবহার করে এবং স্ট্যান্ডার্ড ত্রুটির কিছুই নয়। অন্যদিকে, যদি কোনও আদেশ না পাওয়া যায় তবে এটি কেবল স্ট্যান্ডার্ড ত্রুটি হিসাবে স্থিতিটি প্রতিস্থাপন করে।
ধরে নিচ্ছি আপনি ইতিমধ্যে নিরাপদ শেল অভ্যাস অনুসরণ করছেন :
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 সমর্থিত না , যদিও, এবং কোন বিকল্প আমি যতদূর জানি হয়।
whichএই জন্য সত্য ফিরে।typeযুক্তি ব্যতীত অতিরিক্ত সংরক্ষিত শব্দ এবং শেল বিল্টিনগুলির জন্য সত্য ফিরে আসবে। যদি "প্রোগ্রাম" এর অর্থ "এক্সকিউটেবল ইন$PATH" হয়, তবে এই উত্তরটি দেখুন ।