मैं स्क्रिप्ट के अंदर बैश स्क्रिप्ट फ़ाइल का नाम कैसे निर्धारित कर सकता हूं?
जैसे अगर मेरी स्क्रिप्ट फाइल में है runme.sh
, तो मैं इसे हार्डकॉपी किए बिना "आप रनमे.श" संदेश प्रदर्शित करने के लिए कैसे बनाऊंगा?
मैं स्क्रिप्ट के अंदर बैश स्क्रिप्ट फ़ाइल का नाम कैसे निर्धारित कर सकता हूं?
जैसे अगर मेरी स्क्रिप्ट फाइल में है runme.sh
, तो मैं इसे हार्डकॉपी किए बिना "आप रनमे.श" संदेश प्रदर्शित करने के लिए कैसे बनाऊंगा?
जवाबों:
me=`basename "$0"`
सिम्कलिन 1 के माध्यम से पढ़ने के लिए , जो आमतौर पर आप नहीं चाहते हैं (आप आमतौर पर इस तरह से उपयोगकर्ता को भ्रमित नहीं करना चाहते हैं), कोशिश करें:
me="$(basename "$(test -L "$0" && readlink "$0" || echo "$0")")"
IMO, यह भ्रामक आउटपुट उत्पन्न करेगा। "मैं foo.sh भाग गया, लेकिन यह कह रहा हूँ कि मैं bar.sh चला रहा हूँ !? एक बग होना चाहिए!" इसके अलावा, अलग-अलग नाम वाले सीमलिंक होने के उद्देश्यों में से एक नाम के आधार पर अलग-अलग कार्यक्षमता प्रदान करना है (जैसा कि कुछ प्लेटफार्मों पर gzip और gunzip लगता है)।
1 यही है कि सीमलिंक को हल करने के लिए जब उपयोगकर्ता निष्पादित करता है foo.sh
जो वास्तव में एक सिमलिंक है bar.sh
, तो आप bar.sh
इसके बजाय हल किए गए का उपयोग करना चाहते हैं foo.sh
।
$0
पहले उदाहरण में शब्द बंटवारे के अधीन है, 3. $0
बेसनेम, रीडिंकल और इको में पारित किया जाता है, जो इसे एक कमांड लाइन स्विच के रूप में माना जाता है। । मैं me=$(basename -- "$0")
पठनीयता की कीमत पर इसके बजाय या बहुत अधिक कुशलता से सुझाव देता हूं me=${0##*/}
। सिम्बलिंक के लिए, me=$(basename -- "$(readlink -f -- "$0")")
ग्नू बर्तन को ग्रहण करना, अन्यथा यह एक बहुत लंबी स्क्रिप्ट होगी जिसे मैं यहाँ नहीं लिखूंगा।
# ------------- SCRIPT ------------- #
#!/bin/bash
echo
echo "# arguments called with ----> ${@} "
echo "# \$1 ----------------------> $1 "
echo "# \$2 ----------------------> $2 "
echo "# path to me ---------------> ${0} "
echo "# parent path --------------> ${0%/*} "
echo "# my name ------------------> ${0##*/} "
echo
exit
# ------------- बुलाया ------------- ## ------------- बुलाया ------------- #
# अगली पंक्ति पर ध्यान दें, पहला तर्क डबल के भीतर कहा जाता है, # अगली पंक्ति पर ध्यान दें, पहला तर्क डबल के भीतर कहा जाता है,
# और एकल उद्धरण, क्योंकि इसमें दो शब्द हैं# और एकल उद्धरण, क्योंकि इसमें दो शब्द हैं
$ /misc/shell_scripts/check_root/show_parms.sh "'हैलो वहाँ" "" विलियम "/ misc / shell_scripts / check_root / show_parms । श "" हैलो वहाँ " " "विलियम"
# ------------- परिणाम ------------- ## ------------- परिणाम ------------- #
# तर्क के साथ ---> 'नमस्ते वहाँ' 'विलियम'# तर्क के साथ ---> 'नमस्ते वहाँ' 'विलियम'
# $ 1 ----------------------> 'नमस्ते वहाँ'# $ 1 ----------------------> 'नमस्ते वहाँ'
# $ 2 ----------------------> 'विलियम'# $ 2 ----------------------> 'विलियम'
# मेरे लिए रास्ता --------------> /misc/shell_scripts/check_root/show_parms.sh# मेरे लिए रास्ता --------------> /misc/shell_scripts/check_root/show_parms.sh
# मूल पथ -------------> / misc / shell_scripts / check_root# मूल पथ -------------> / misc / shell_scripts / check_root
# मेरा नाम -----------------> show_parms.sh# मेरा नाम -----------------> show_parms.sh
# ------------- समाप्त ------------- ## ------------- समाप्त ------------- #
show_params
बिना किसी वैकल्पिक विस्तार के बस नाम कैसे प्राप्त कर सकता हूं ?
${0##*/}
। GitBash का उपयोग करके परीक्षण किया गया।
बैश के साथ > = 3 निम्नलिखित कार्य करता है:
$ ./s
0 is: ./s
BASH_SOURCE is: ./s
$ . ./s
0 is: bash
BASH_SOURCE is: ./s
$ cat s
#!/bin/bash
printf '$0 is: %s\n$BASH_SOURCE is: %s\n' "$0" "$BASH_SOURCE"
dirname $BASE_SOURCE
निर्देशिकाओं को प्राप्त करने के लिए आसानी से " " का उपयोग करना है जो स्क्रिप्ट स्थित हैं।
$BASH_SOURCE
स्क्रिप्ट सोर्स करते समय सही उत्तर देता है।
हालाँकि, इसमें स्क्रिप्ट नाम फ़ाइल करने के लिए केवल पथ का उपयोग करना शामिल है:
$(basename $BASH_SOURCE)
. <filename> [arguments]
, $0
कॉल करने वाले का नाम बता देंगे। कम से कम OSX पर सुनिश्चित करने के लिए।
स्क्रिप्ट नाम उस में रिक्त स्थान है, तो एक और अधिक मजबूत तरीके से उपयोग करने के लिए है "$0"
या "$(basename "$0")"
- या MacOS पर: "$(basename \"$0\")"
। यह किसी भी तरह से नाम को आम होने या व्याख्या करने से रोकता है। सामान्य तौर पर, शेल में चर नामों को हमेशा डबल करना अच्छा होता है।
यदि आप इसे बिना रास्ते के चाहते हैं तो आप उपयोग करेंगे ${0##*/}
लिनक्स पर क्रिस कॉनवे का जवाब देने के लिए (कम से कम) आप ऐसा करेंगे:
echo $(basename $(readlink -nf $0))
readlink एक प्रतीकात्मक लिंक के मूल्य को प्रिंट करता है। यदि यह एक प्रतीकात्मक लिंक नहीं है, तो यह फ़ाइल नाम को प्रिंट करता है। -नई से कहता है कि नई लाइन न छापें। -यदि यह पूरी तरह से लिंक का पालन करने के लिए कहता है (यदि एक प्रतीकात्मक लिंक किसी अन्य लिंक का लिंक होता है, तो यह उस एक को भी हल करेगा)।
मैंने इस लाइन को हमेशा काम करने के लिए पाया है, भले ही फ़ाइल को स्क्रिप्ट के रूप में सॉर्ट किया जा रहा हो या चलाया जा रहा हो।
echo "${BASH_SOURCE[${#BASH_SOURCE[@]} - 1]}"
यदि आप readlink
अपने ऊपर मिलने वाले पथ पर, पुनरावर्ती या गैर-पुनरावर्ती रूप से उपयोग किए जाने वाले सिमिलिंक का अनुसरण करना चाहते हैं ।
एक-लाइनर कार्यों का कारण BASH_SOURCE
पर्यावरण चर और इसके सहयोगी के उपयोग द्वारा समझाया गया है FUNCNAME
।
BASH_SOURCE
एक सरणी चर जिसका सदस्य स्रोत फ़ाइल नाम हैं, जहां FUNCNAME सरणी चर में संबंधित शेल फ़ंक्शन नाम परिभाषित किए गए हैं। शेल फ़ंक्शन $ {FUNCNAME [$ i]} को $ {BASH_SOURCE [$ i]} में परिभाषित किया गया है और $ {BASH_SOURCE [$ i + 1]} से बुलाया गया है।
FUNCNAME
एक शेल वैरिएबल जिसमें सभी शेल फ़ंक्शंस के नाम हैं जो वर्तमान में निष्पादन कॉल स्टैक में हैं। इंडेक्स 0 वाला तत्व किसी भी वर्तमान में निष्पादित शेल फ़ंक्शन का नाम है। सबसे नीचे का तत्व (उच्चतम सूचकांक वाला) "मुख्य" है। यह चर केवल तब होता है जब शेल फ़ंक्शन निष्पादित हो रहा हो। FUNCNAME को असाइनमेंट का कोई प्रभाव नहीं है और एक त्रुटि स्थिति लौटाता है। यदि FUNCNAME परेशान है, तो यह अपने विशेष गुणों को खो देता है, भले ही यह बाद में रीसेट हो।
इस चर का उपयोग BASH_LINENO और BASH_SOURCE के साथ किया जा सकता है। FUNCNAME के प्रत्येक तत्व में कॉल स्टैक का वर्णन करने के लिए BASH_LINENO और BASH_SOURCE में संबंधित तत्व हैं। उदाहरण के लिए, $ {FUNCNAME [$ i]} को फ़ाइल से $ {BASH_SOURCE [$ i + 1]} लाइन नंबर $ {BASH_LINENO [$ i]} पर कॉल किया गया था। इस जानकारी का उपयोग कर कॉल करने वाला बिलियन वर्तमान कॉल स्टैक को प्रदर्शित करता है।
[स्रोत: बैश मैनुअल]
a
(मान लें कि a
सामग्री है echo "${BASH_SOURCE[${#BASH_SOURCE[@]} - 1]}"
) - तो यह आपको a
रास्ता देगा। लेकिन अगर आप इसके b
साथ एक स्क्रिप्ट लिखते हैं source a
और चलाते हैं ./b
, तो यह वापस आ जाएगी b
।
ये उत्तर उन मामलों के लिए सही हैं जो वे कहते हैं, लेकिन एक समस्या अभी भी है यदि आप 'स्रोत' कीवर्ड का उपयोग करके किसी अन्य स्क्रिप्ट से स्क्रिप्ट चलाते हैं (ताकि यह उसी शेल में चलता है)। इस स्थिति में, आपको कॉलिंग स्क्रिप्ट का $ 0 मिलता है। और इस मामले में, मुझे नहीं लगता कि स्क्रिप्ट का नाम ही संभव है।
यह एक एज केस है और इसे टीओओ को गंभीरता से नहीं लेना चाहिए। यदि आप स्क्रिप्ट को दूसरी स्क्रिप्ट से सीधे ('स्रोत' के बिना) चलाते हैं, तो $ 0 का उपयोग करना काम करेगा।
चूंकि कुछ टिप्पणियों ने विस्तार के बिना फ़ाइल नाम के बारे में पूछा, यहां एक उदाहरण दिया गया है कि इसे कैसे पूरा किया जाए:
FileName=${0##*/}
FileNameWithoutExtension=${FileName%.*}
का आनंद लें!
पुन: टंकटालस (स्वीकृत) से ऊपर का उत्तर, थोड़ा साफ करने का तरीका उपयोग करना है:
me=$(readlink --canonicalize --no-newline $0)
यदि आपकी स्क्रिप्ट को किसी अन्य बैश स्क्रिप्ट से अलग कर दिया गया है, तो आप इसका उपयोग कर सकते हैं:
me=$(readlink --canonicalize --no-newline $BASH_SOURCE)
मैं मानता हूं कि अगर आपके उद्देश्य उपयोगकर्ता को प्रतिक्रिया प्रदान करना है, तो यह आपके लिए सहानुभूति को भ्रमित करने वाला होगा, लेकिन ऐसे मौके भी आते हैं जब आपको किसी स्क्रिप्ट या अन्य फ़ाइल में विहित नाम प्राप्त करने की आवश्यकता होती है, और यह सबसे अच्छा तरीका है, imo।
source
D स्क्रिप्ट नामों के लिए धन्यवाद ।
अगर आपका आह्वान शेल स्क्रिप्ट की तरह है
/home/mike/runme.sh
$ 0 पूरा नाम है
/home/mike/runme.sh
basename $ 0 को आधार फ़ाइल नाम मिलेगा
runme.sh
और आपको इस मूल नाम को एक चर में रखना होगा
filename=$(basename $0)
और अपना अतिरिक्त पाठ जोड़ें
echo "You are running $filename"
इसलिए आपकी स्क्रिप्ट पसंद है
/home/mike/runme.sh
#!/bin/bash
filename=$(basename $0)
echo "You are running $filename"
this="$(dirname "$(realpath "$BASH_SOURCE")")"
यह प्रतीकात्मक लिंक (realpath ऐसा करता है) को हल करता है, रिक्त स्थान को संभालता है (दोहरा उद्धरण ऐसा करता है), और खट्टा होने पर भी वर्तमान स्क्रिप्ट का नाम खोजेगा (./myscript) या अन्य लिपियों द्वारा बुलाया ($ BASH_SOURCE हैंडल)। आखिरकार, इसे पर्यावरण के चर में फिर से उपयोग करने के लिए या आसान कॉपी के लिए कहीं और सहेजना अच्छा है (यह =) ...
realpath
करना बिल्ट-इन BASH कमांड नहीं है। यह एक स्टैंडअलोन निष्पादन योग्य है जो केवल कुछ वितरणों में उपलब्ध है
में bash
आप का उपयोग कर स्क्रिप्ट फ़ाइल नाम प्राप्त कर सकते हैं $0
। आम तौर पर $1
, $2
आदि सीएलआई तर्कों का उपयोग करते हैं। इसी तरह $0
उस नाम को एक्सेस करना है जो स्क्रिप्ट (स्क्रिप्ट फ़ाइल नाम) को ट्रिगर करता है।
#!/bin/bash
echo "You are running $0"
...
...
यदि आप स्क्रिप्ट को पथ के साथ लागू करते हैं, /path/to/script.sh
तो $0
पथ के साथ फ़ाइल नाम भी देंगे। उस मामले में $(basename $0)
केवल स्क्रिप्ट फ़ाइल नाम प्राप्त करने के लिए उपयोग करने की आवश्यकता है ।
$0
सवाल का जवाब नहीं देता (जैसा कि मैं इसे समझता हूं)। प्रदर्शन:
$ बिल्ली लिपि #! / Bin / श गूंज `बेसन $ 0` $ ./script.sh script.sh $ ln script.sh लिंकटोसस्क्रिप्ट $ ./linktoscript linktoscript
किसी ./linktoscript
को प्रिंट आउट कैसे मिलता है script.sh
?
[EDIT] प्रति टिप्पणी में @ephemient के ऊपर, हालांकि प्रतीकात्मक लिंक चीज़ से विवाद हो सकता है, $0
इस तरह से फ़ेल्ड करना संभव है कि यह एक फ़ाइल सिस्टम संसाधन का प्रतिनिधित्व नहीं करता है। ओपी थोड़ा अस्पष्ट है कि वह क्या चाहता है।
बिल हर्नांडेज़ को जानकारी धन्यवाद। मैंने कुछ प्राथमिकताएँ जोड़ीं, जिन्हें मैं अपना रहा हूँ।
#!/bin/bash
function Usage(){
echo " Usage: show_parameters [ arg1 ][ arg2 ]"
}
[[ ${#2} -eq 0 ]] && Usage || {
echo
echo "# arguments called with ----> ${@} "
echo "# \$1 -----------------------> $1 "
echo "# \$2 -----------------------> $2 "
echo "# path to me ---------------> ${0} " | sed "s/$USER/\$USER/g"
echo "# parent path --------------> ${0%/*} " | sed "s/$USER/\$USER/g"
echo "# my name ------------------> ${0##*/} "
echo
}
चियर्स
लघु, स्पष्ट और सरल, में my_script.sh
#!/bin/bash
running_file_name=$(basename "$0")
echo "You are running '$running_file_name' file."
बाहर रखा:
./my_script.sh
You are running 'my_script.sh' file.
DIRECTORY=$(cd `dirname $0` && pwd)
मुझे एक और स्टैक ओवरफ्लो प्रश्न से ऊपर मिला, क्या एक बैश स्क्रिप्ट बता सकती है कि यह किस निर्देशिका में संग्रहीत है? , लेकिन मुझे लगता है कि यह इस विषय के लिए भी उपयोगी है।
यहाँ मैं दिमित्रे रादोलोव के उत्तर से प्रेरित होकर आया हूं (जो कि मैंने उतारा है, वैसे) ।
script="$BASH_SOURCE"
[ -z "$BASH_SOURCE" ] && script="$0"
echo "Called $script with $# argument(s)"
आपके स्क्रिप्ट को कॉल करने के तरीके की परवाह किए बिना
. path/to/script.sh
या
./path/to/script.sh
कुछ इस तरह से?
export LC_ALL=en_US.UTF-8
#!/bin/bash
#!/bin/sh
#----------------------------------------------------------------------
start_trash(){
ver="htrash.sh v0.0.4"
$TRASH_DIR # url to trash $MY_USER
$TRASH_SIZE # Show Trash Folder Size
echo "Would you like to empty Trash [y/n]?"
read ans
if [ $ans = y -o $ans = Y -o $ans = yes -o $ans = Yes -o $ans = YES ]
then
echo "'yes'"
cd $TRASH_DIR && $EMPTY_TRASH
fi
if [ $ans = n -o $ans = N -o $ans = no -o $ans = No -o $ans = NO ]
then
echo "'no'"
fi
return $TRUE
}
#-----------------------------------------------------------------------
start_help(){
echo "HELP COMMANDS-----------------------------"
echo "htest www open a homepage "
echo "htest trash empty trash "
return $TRUE
} #end Help
#-----------------------------------------------#
homepage=""
return $TRUE
} #end cpdebtemp
# -Case start
# if no command line arg given
# set val to Unknown
if [ -z $1 ]
then
val="*** Unknown ***"
elif [ -n $1 ]
then
# otherwise make first arg as val
val=$1
fi
# use case statement to make decision for rental
case $val in
"trash") start_trash ;;
"help") start_help ;;
"www") firefox $homepage ;;
*) echo "Sorry, I can not get a $val for you!";;
esac
# Case stop