Komut dosyasının içindeki Bash komut dosyasının adını nasıl belirleyebilirim?
Eğer runme.sh
betiğim dosyadaysa, o zaman bunu kodlamadan "runme.sh çalıştırıyorsunuz" mesajını görüntülemeyi nasıl sağlarım?
Komut dosyasının içindeki Bash komut dosyasının adını nasıl belirleyebilirim?
Eğer runme.sh
betiğim dosyadaysa, o zaman bunu kodlamadan "runme.sh çalıştırıyorsunuz" mesajını görüntülemeyi nasıl sağlarım?
Yanıtlar:
me=`basename "$0"`
Genellikle istediğiniz şey olmayan bir symlink 1 ile okumak için (genellikle kullanıcıyı bu şekilde karıştırmak istemezsiniz) deneyin:
me="$(basename "$(test -L "$0" && readlink "$0" || echo "$0")")"
IMO, kafa karıştırıcı çıktılar üretecek. "Foo.sh'ı çalıştırdım, ama bar.sh çalıştırdığımı söylüyor !? Bir hata olmalı!" Ayrıca, farklı adlandırılmış sembollere sahip olmanın amaçlarından biri, adı verilen isme göre farklı işlevsellik sağlamaktır (bazı platformlarda gzip ve gunzip'i düşünün).
1 Yani, sembolik bağlantıları çözmek için, kullanıcı foo.sh
aslında bir sembolik bağlantı yürüttüğünde, bunun yerine bar.sh
çözümlenmiş adı kullanmak istersiniz .bar.sh
foo.sh
$0
ilk örnekte kelime bölmeye tabidir, 3. $0
bir komut satırı anahtarı olarak işlem görmesini sağlayan bir konumda basename, readlink ve echo'ya geçirilir . Bunun yerine me=$(basename -- "$0")
ya da çok daha verimli bir şekilde okunabilirlik pahasına öneriyorum me=${0##*/}
. Simgeler için, me=$(basename -- "$(readlink -f -- "$0")")
gnu araçlarını varsayarsak, aksi takdirde burada yazmayacağım çok uzun bir komut dosyası olacaktır.
# ------------- SENARYO ------------- # # ------------- ÇAĞRI ------ ------- #
#!/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
# Sonraki satırda dikkat edin, ilk argüman iki kelime içerdiğinden çift, # ve tek tırnak içinde çağrılır
$ / misc / shell_scripts / check_root / show_parms . sh "" merhaba orada "" "" william "
# ------------- SONUÇLAR ------------- #
# argüman çağrıldı ---> 'merhaba orada' 'william' # $ 1 ----------------------> 'merhaba orada' # 2 $ ---- ------------------> 'william' # bana giden yol --------------> / misc / shell_scripts / check_root / show_parms. sh # üst yol -------------> / misc / shell_scripts / check_root # benim adım -----------------> show_parms.sh
# ------------- SON ------------- #
show_params
, yani isteğe bağlı uzantısı olmayan adı nasıl alabilirim ?
${0##*/}
,. GitBash kullanılarak test edildi.
İle bash> = 3 aşağıdaki işler:
$ ./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
budur ve komut dosyalarının bulunduğu dizini almak için " " kullanmak kolaydır .
$BASH_SOURCE
betiği kaynaklarken doğru cevabı verir.
Ancak bu, yalnızca komut dosyalarının dosya adını almak için şu yolu içerir:
$(basename $BASH_SOURCE)
. <filename> [arguments]
, $0
arayan kabuğun ismini verecekti. En azından OSX'te kesin.
Komut dosyası adında boşluklar varsa, "$0"
veya "$(basename "$0")"
- veya MacOS: 'da daha sağlam bir yol kullanmaktır "$(basename \"$0\")"
. Bu, adın herhangi bir şekilde karıştırılmasını veya yorumlanmasını önler. Genel olarak, her zaman kabuktaki değişken isimlerini çift tırnak içine almak iyi bir uygulamadır.
Chris Conway'e cevap vermek için Linux'ta (en azından) bunu yaparsınız:
echo $(basename $(readlink -nf $0))
readlink, sembolik bir bağlantının değerini yazdırır. Sembolik bir bağlantı değilse, dosya adını yazdırır. -n bir satırsonu yazdırmamasını söyler. -f bağlantıyı tamamen izlemesini söyler (eğer sembolik bir bağlantı başka bir bağlantının bağlantısıysa, o bağlantıyı da çözer).
Ben dosya kaynak olup olmadığını veya bir komut dosyası olarak çalıştırmak olsun, her zaman çalışmak için bu satırı buldum.
echo "${BASH_SOURCE[${#BASH_SOURCE[@]} - 1]}"
Symlinks'i takip etmek istiyorsanız, readlink
yukarıdaki, yinelemeli veya yinelemesiz olarak kullandığınız yolda kullanın .
Tek astarın çalışmasının nedeni, BASH_SOURCE
ortam değişkeninin ve bunun ilişkilendiricisinin kullanımı ile açıklanmaktadır FUNCNAME
.
BASH_SOURCE
Üyeleri FUNCNAME dizi değişkenindeki karşılık gelen kabuk işlev adlarının tanımlandığı kaynak dosya adları olan bir dizi değişkeni. $ {FUNCNAME [$ i]} kabuk işlevi $ {BASH_SOURCE [$ i]} dosyasında tanımlanmış ve $ {BASH_SOURCE [$ i + 1]} dosyasından çağrılmıştır.
FUNCNAME
Yürütme çağrısı yığınında bulunan tüm kabuk işlevlerinin adlarını içeren bir dizi değişkeni. 0 dizinine sahip öğe, şu anda yürütülen herhangi bir kabuk işlevinin adıdır. En alttaki eleman (en yüksek endekse sahip olan eleman) "ana" dır. Bu değişken yalnızca bir kabuk işlevi yürütüldüğünde mevcuttur. FUNCNAME öğesine yapılan atamaların hiçbir etkisi yoktur ve hata durumu döndürür. FUNCNAME ayarlanmamışsa, daha sonra sıfırlansa bile özel özelliklerini kaybeder.
Bu değişken BASH_LINENO ve BASH_SOURCE ile kullanılabilir. FUNCNAME öğesinin her öğesinde, çağrı yığınını açıklamak için BASH_LINENO ve BASH_SOURCE öğelerinde karşılık gelen öğeler bulunur. Örneğin $ {FUNCNAME [$ i]}, $ {BASH_SOURCE [$ i + 1]} dosyasından $ {BASH_LINENO [$ i]} satır numarasından çağrıldı. Arayan yerleşik, bu bilgiyi kullanarak geçerli çağrı yığınını görüntüler.
\. [Kaynak: Bash kılavuzu]
a
varsayalım ) çalışır - o zaman size yol verir. Eğer bir senaryo yazmak Ama eğer birlikte o ve koşmak , bu dönersiniz 'ın yolunu. a
echo "${BASH_SOURCE[${#BASH_SOURCE[@]} - 1]}"
a
b
source a
./b
b
Bu yanıtlar belirttikleri durumlar için doğrudur, ancak komut dosyasını 'source' anahtar sözcüğünü kullanarak (aynı kabukta çalışacak şekilde) başka bir komut dosyasından çalıştırırsanız hala bir sorun vardır. Bu durumda, çağıran komut dosyasının $ 0'ını alırsınız. Ve bu durumda, betiğin adını almanın mümkün olduğunu düşünmüyorum.
Bu bir uç durumdur ve çok ciddiye alınmamalıdır. Komut dosyasını başka bir komut dosyasından doğrudan çalıştırırsanız ('kaynak' olmadan), $ 0 kullanmak işe yarayacaktır.
Bazı yorumlar uzantısız dosya adı hakkında sorduğundan, bunun nasıl yapılacağına dair bir örnek:
FileName=${0##*/}
FileNameWithoutExtension=${FileName%.*}
Zevk almak!
Re: Tanktalus'un (kabul edilen) yukarıdaki cevabı, biraz daha temiz bir yol kullanmaktır:
me=$(readlink --canonicalize --no-newline $0)
Betiğiniz başka bir bash betiğinden alınmışsa aşağıdakileri kullanabilirsiniz:
me=$(readlink --canonicalize --no-newline $BASH_SOURCE)
Amacınız kullanıcıya geri bildirimde bulunmak için sembolik bağlantıları kaldırmanın kafa karıştırıcı olacağını kabul ediyorum, ancak kanonik adı bir komut dosyasına veya başka bir dosyaya almanız gerektiğinde durumlar vardır ve bu en iyi yoldur, imo.
source
D komut dosyası adları için teşekkürler .
kabuk komut dosyanız gibi
/home/mike/runme.sh
$ 0 tam ad
/home/mike/runme.sh
basename $ 0 temel dosya adını alacak
runme.sh
ve bu temel adı aşağıdaki gibi bir değişkene
filename=$(basename $0)
ve ek metninizi ekleyin
echo "You are running $filename"
yani senaryonun
/home/mike/runme.sh
#!/bin/bash
filename=$(basename $0)
echo "You are running $filename"
this="$(dirname "$(realpath "$BASH_SOURCE")")"
Bu, sembolik bağlantıları çözer (realpath bunu yapar), boşlukları (çift tırnak işaretleri bunu yapar) ve kaynak ((. ./Myscript) veya diğer komut dosyaları tarafından çağrıldığında ($ BASH_SOURCE bunu işler) bile geçerli komut dosyasının adını bulur. Tüm bunlardan sonra, bunu yeniden kullanmak veya başka bir yerde kolay kopyalamak için bir ortam değişkenine kaydetmek iyidir (this =) ...
realpath
yerleşik bir BASH komutu değildir. Yalnızca belirli dağıtımlarda kullanılabilen bağımsız bir yürütülebilir
İçinde bash
komut dosyası dosyasının adını kullanarak alabilirsiniz $0
. Genellikle $1
, $2
vb erişim CLI bağımsız değişkendir. Benzer şekilde $0
, komut dosyasını (komut dosyası adı) tetikleyen ada erişmek için kullanılır.
#!/bin/bash
echo "You are running $0"
...
...
Eğer böyle yol ile komut çağırmak durumunda /path/to/script.sh
o zaman $0
da yol ile dosya adını verecektir. Bu durumda $(basename $0)
yalnızca komut dosyası adı almak için kullanmanız gerekir .
$0
soruyu cevaplamıyor (anladığım kadarıyla). Bir gösteri:
$ cat script.sh #! / Bin / sh echo `basename $ 0` $ ./script.sh script.sh $ ln script.sh linktoscript $ ./linktoscript linktoscript
Kişi nasıl ./linktoscript
çıktı alabilir script.sh
?
[EDIT] Yukarıdaki yorumlarda @ephemient başına, sembolik bağlantı olayı anlaşılmış görünse de, $0
bir dosya sistemi kaynağını temsil etmeyecek şekilde uğraşmak mümkündür . OP istediği konusunda biraz belirsiz.
Bill Hernandez sayesinde bilgi. Kabul ettiğim bazı tercihler ekledim.
#!/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
}
Şerefe
Kısa, net ve basit, my_script.sh
#!/bin/bash
running_file_name=$(basename "$0")
echo "You are running '$running_file_name' file."
Çıktı:
./my_script.sh
You are running 'my_script.sh' file.
DIRECTORY=$(cd `dirname $0` && pwd)
Yukarıdakileri başka bir Stack Overflow sorusundan aldım, Bash betiği hangi dizinde depolandığını söyleyebilir mi? , ancak bu konu için de yararlı olduğunu düşünüyorum.
İşte esinlenerek ile geldi budur Dimitre Radoulov 'ın cevabı (Bu arada, upvoted olan) .
script="$BASH_SOURCE"
[ -z "$BASH_SOURCE" ] && script="$0"
echo "Called $script with $# argument(s)"
senaryonuzu nasıl çağırdığınızdan bağımsız olarak
. path/to/script.sh
veya
./path/to/script.sh
böyle bir şey?
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