Comment puis-je déterminer le nom du fichier de script Bash à l'intérieur du script lui-même?
Comme si mon script est dans un fichier runme.sh
, comment puis-je faire pour afficher le message "Vous exécutez runme.sh" sans coder en dur cela?
Comment puis-je déterminer le nom du fichier de script Bash à l'intérieur du script lui-même?
Comme si mon script est dans un fichier runme.sh
, comment puis-je faire pour afficher le message "Vous exécutez runme.sh" sans coder en dur cela?
Réponses:
me=`basename "$0"`
Pour lire un lien symbolique 1 , qui n'est généralement pas ce que vous voulez (vous ne voulez généralement pas confondre l'utilisateur de cette façon), essayez:
me="$(basename "$(test -L "$0" && readlink "$0" || echo "$0")")"
OMI, cela produira une sortie déroutante. "J'ai lancé foo.sh, mais ça veut dire que je lance bar.sh!? Ça doit être un bug!" En outre, l'un des buts d'avoir des liens symboliques différemment nommés est de fournir des fonctionnalités différentes en fonction du nom sous lequel il est appelé (pensez à gzip et gunzip sur certaines plates-formes).
1 C'est-à-dire, pour résoudre les liens symboliques de telle sorte que lorsque l'utilisateur exécute foo.sh
qui est en fait un lien symbolique vers bar.sh
, vous souhaitez utiliser le nom résolu bar.sh
plutôt que foo.sh
.
$0
dans le premier exemple est sujet à la séparation des mots, 3. $0
est passé au nom de base, readlink et écho dans une position qui lui permet d'être traité comme un commutateur de ligne de commande . Je suggère plutôt me=$(basename -- "$0")
ou beaucoup plus efficace au détriment de la lisibilité, me=${0##*/}
. Pour les liens symboliques, en me=$(basename -- "$(readlink -f -- "$0")")
supposant les utils gnu, sinon ce sera un script très long que je n'écrirai pas ici.
# ------------- SCRIPT ------------- # # ------------- APPELÉ ------ ------- #
#!/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
# Remarquez sur la ligne suivante, le premier argument est appelé entre guillemets doubles, # et simples, car il contient deux mots
$ / misc / shell_scripts / check_root / show_parms . sh "'bonjour là" " "' william '"
# ------------- RÉSULTATS ------------- #
# arguments appelés avec ---> 'bonjour là' 'william' # $ 1 ----------------------> 'bonjour là' # $ 2 ---- ------------------> 'william' # chemin vers moi --------------> / misc / shell_scripts / check_root / show_parms. sh # parent path -------------> / misc / shell_scripts / check_root # my name -----------------> show_parms.sh
# ------------- FIN ------------- #
show_params
, c'est-à-dire le nom sans extension facultative?
${0##*/}
. Testé à l'aide de GitBash.
Avec bash> = 3 les travaux suivants:
$ ./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
" pour obtenir le répertoire que les scripts ont localisé.
$BASH_SOURCE
donne la bonne réponse lors de la recherche du script.
Cependant, cela inclut le chemin d'accès pour obtenir uniquement le nom de fichier des scripts, utilisez:
$(basename $BASH_SOURCE)
. <filename> [arguments]
, $0
donnerait le nom du shell de l'appelant. Bien au moins sur OSX, c'est sûr.
Si le nom du script comporte des espaces, d' une manière plus robuste est d'utiliser "$0"
ou "$(basename "$0")"
- ou sur MacOS: "$(basename \"$0\")"
. Cela empêche le nom d'être altéré ou interprété de quelque manière que ce soit. En général, il est recommandé de toujours mettre des noms de variable entre guillemets dans le shell.
Si vous le souhaitez sans le chemin, vous utiliserez ${0##*/}
Pour répondre à Chris Conway , sur Linux (au moins), vous feriez ceci:
echo $(basename $(readlink -nf $0))
readlink imprime la valeur d'un lien symbolique. S'il ne s'agit pas d'un lien symbolique, il imprime le nom du fichier. -n lui dit de ne pas imprimer de nouvelle ligne. -f lui dit de suivre complètement le lien (si un lien symbolique était un lien vers un autre lien, il le résoudrait également).
J'ai trouvé que cette ligne fonctionnait toujours, que le fichier soit d'origine ou exécuté en tant que script.
echo "${BASH_SOURCE[${#BASH_SOURCE[@]} - 1]}"
Si vous souhaitez suivre l'utilisation des liens symboliques readlink
sur le chemin que vous obtenez ci-dessus, récursivement ou non récursivement.
La raison pour laquelle le one-liner fonctionne s'explique par l'utilisation de la BASH_SOURCE
variable d'environnement et de son associé FUNCNAME
.
BASH_SOURCE
Variable de tableau dont les membres sont les noms de fichiers source où les noms de fonction shell correspondants dans la variable de tableau FUNCNAME sont définis. La fonction shell $ {FUNCNAME [$ i]} est définie dans le fichier $ {BASH_SOURCE [$ i]} et appelée depuis $ {BASH_SOURCE [$ i + 1]}.
FUNCNAME
Une variable de tableau contenant les noms de toutes les fonctions shell actuellement dans la pile des appels d'exécution. L'élément d'index 0 est le nom de toute fonction shell en cours d'exécution. L'élément le plus bas (celui dont l'indice est le plus élevé) est "principal". Cette variable n'existe que lorsqu'une fonction shell est en cours d'exécution. Les affectations à FUNCNAME n'ont aucun effet et renvoient un état d'erreur. Si FUNCNAME n'est pas défini, il perd ses propriétés spéciales, même s'il est ensuite réinitialisé.
Cette variable peut être utilisée avec BASH_LINENO et BASH_SOURCE. Chaque élément de FUNCNAME a des éléments correspondants dans BASH_LINENO et BASH_SOURCE pour décrire la pile d'appels. Par exemple, $ {FUNCNAME [$ i]} a été appelé à partir du fichier $ {BASH_SOURCE [$ i + 1]} au numéro de ligne $ {BASH_LINENO [$ i]}. La fonction intégrée de l'appelant affiche la pile d'appels actuelle à l'aide de ces informations.
[Source: manuel Bash]
a
(supposons que a
le contenu est echo "${BASH_SOURCE[${#BASH_SOURCE[@]} - 1]}"
) à partir d'une session interactive - alors il vous donnera a
le chemin. Mais si vous écrivez un script b
avec source a
et que vous l'exécutez ./b
, il retournera b
le chemin d'accès.
Ces réponses sont correctes pour les cas qu'elles indiquent mais il y a toujours un problème si vous exécutez le script à partir d'un autre script en utilisant le mot-clé 'source' (afin qu'il s'exécute dans le même shell). Dans ce cas, vous obtenez le $ 0 du script appelant. Et dans ce cas, je ne pense pas qu'il soit possible d'obtenir le nom du script lui-même.
Il s'agit d'un cas de bord et ne doit pas être pris trop au sérieux. Si vous exécutez le script à partir d'un autre script directement (sans «source»), l'utilisation de $ 0 fonctionnera.
Étant donné que certains commentaires portaient sur le nom de fichier sans extension, voici un exemple comment y parvenir:
FileName=${0##*/}
FileNameWithoutExtension=${FileName%.*}
Prendre plaisir!
Re: Réponse de Tanktalus (acceptée) ci-dessus, une manière légèrement plus propre consiste à utiliser:
me=$(readlink --canonicalize --no-newline $0)
Si votre script provient d'un autre script bash, vous pouvez utiliser:
me=$(readlink --canonicalize --no-newline $BASH_SOURCE)
Je conviens qu'il serait déroutant de déréférencer les liens symboliques si votre objectif est de fournir des commentaires à l'utilisateur, mais il y a des occasions où vous avez besoin d'obtenir le nom canonique d'un script ou d'un autre fichier, et c'est la meilleure façon, imo.
source
noms de script d.
si votre script shell d'invocation comme
/home/mike/runme.sh
$ 0 est le nom complet
/home/mike/runme.sh
nom de base $ 0 obtiendra le nom du fichier de base
runme.sh
et vous devez mettre ce nom de base dans une variable comme
filename=$(basename $0)
et ajoutez votre texte supplémentaire
echo "You are running $filename"
donc vos scripts comme
/home/mike/runme.sh
#!/bin/bash
filename=$(basename $0)
echo "You are running $filename"
this="$(dirname "$(realpath "$BASH_SOURCE")")"
Cela résout les liens symboliques (realpath fait cela), gère les espaces (les guillemets doubles font cela) et trouvera le nom du script actuel même lorsqu'il est source (. ./Myscript) ou appelé par d'autres scripts ($ BASH_SOURCE gère cela). Après tout cela, il est bon de l'enregistrer dans une variable d'environnement pour une réutilisation ou pour une copie facile ailleurs (this =) ...
realpath
n'est pas une commande BASH intégrée. Il s'agit d'un exécutable autonome qui n'est disponible que dans certaines distributions
Dans bash
vous pouvez obtenir le nom du fichier de script en utilisant $0
. Généralement $1
, $2
etc sont pour accéder aux arguments CLI. Il en va de même $0
pour accéder au nom qui déclenche le script (nom du fichier script).
#!/bin/bash
echo "You are running $0"
...
...
Si vous invoquez le script avec path comme /path/to/script.sh
alors, vous $0
obtiendrez également le nom de fichier avec path. Dans ce cas, vous devez utiliser $(basename $0)
pour obtenir uniquement le nom du fichier de script.
$0
ne répond pas à la question (si je comprends bien). Une démonstration:
$ cat script.sh #! / bin / sh echo `nom de base $ 0` $ ./script.sh script.sh $ ln script.sh linktoscript $ ./linktoscript linktoscript
Comment ./linktoscript
imprimer script.sh
?
[EDIT] Par @ephemient dans les commentaires ci-dessus, bien que le lien symbolique puisse sembler artificiel, il est possible de jouer avec $0
tel qu'il ne représente pas une ressource de système de fichiers. L'OP est un peu ambigu sur ce qu'il voulait.
Info grâce à Bill Hernandez. J'ai ajouté quelques préférences que j'adopte.
#!/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
}
À votre santé
Court, clair et simple, en my_script.sh
#!/bin/bash
running_file_name=$(basename "$0")
echo "You are running '$running_file_name' file."
Production:
./my_script.sh
You are running 'my_script.sh' file.
DIRECTORY=$(cd `dirname $0` && pwd)
J'ai obtenu ce qui précède d'une autre question de débordement de pile, un script Bash peut-il indiquer dans quel répertoire il est stocké? , mais je pense que c'est également utile pour ce sujet.
Voici ce que je suis venu avec, inspiré par Dimitre Radoulov réponse de (que j'upvoted, par la voie) .
script="$BASH_SOURCE"
[ -z "$BASH_SOURCE" ] && script="$0"
echo "Called $script with $# argument(s)"
quelle que soit la façon dont vous appelez votre script
. path/to/script.sh
ou
./path/to/script.sh
quelque chose comme ça?
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