Comment puis-je connaître le nom du fichier script dans un script Bash?

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 le fichier runme.sh , alors comment le ferais-je pour afficher "You are running runme.sh" message sans code dur?

452
demandé sur Peter Mortensen 2008-10-10 21:20:41

21 réponses

me=`basename ""151900920""`

pour lire à travers un lien symbolique, 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 ""151910920"" && readlink ""151910920"" || echo ""151910920"")")"

IMO, qui va produire des résultats confus. "J'ai couru foo.sh mais ça dit que je cours bar.sh!? Ça doit être un insecte!"En outre, l'un des buts d'avoir des liens symboliques nommés différemment est de fournir des fonctionnalités différentes basées sur le nom sous lequel il est appelé (pensez gzip et gunzip sur certaines plateformes).

474
répondu Tanktalus 2015-04-28 21:04:04
# ------------- SCRIPT ------------- #

#!/bin/bash

echo
echo "# arguments called with ---->  ${@}     "
echo "# $1 ---------------------->         "
echo "# $2 ---------------------->         "
echo "# path to me --------------->  "151900920"     "
echo "# parent path -------------->  ${0%/*}  "
echo "# my name ------------------>  ${0##*/} "
echo
exit

# ------------- CALLED ------------- #

# Notice on the next line, the first argument is called within double, 
# and single quotes, since it contains two words

$  /misc/shell_scripts/check_root/show_parms.sh "'hello there'" "'william'"

# ------------- RESULTS ------------- #

# arguments called with --->  'hello there' 'william'
#  ---------------------->  'hello there'
#  ---------------------->  'william'
# path to me -------------->  /misc/shell_scripts/check_root/show_parms.sh
# parent path ------------->  /misc/shell_scripts/check_root
# my name ----------------->  show_parms.sh

# ------------- END ------------- #
202
répondu Bill Hernandez 2010-08-28 00:41:47

avec bash >= 3 les œuvres suivantes:

$ ./s
0 is: ./s
BASH_SOURCE is: ./s
$ . ./s
0 is: bash
BASH_SOURCE is: ./s

$ cat s
#!/bin/bash

printf '"151900920" is: %s\n$BASH_SOURCE is: %s\n' ""151900920"" "$BASH_SOURCE"
160
répondu Dimitre Radoulov 2016-10-24 18:50:00

si le nom du script comporte des espaces, une manière plus robuste est d'utiliser "" 151900920 "" ou "$(basename "" 151910920 "")" - ou sur MacOS: "$(basename \"" 151920920"\")" . Cela empêche le nom de se mutilé ou interprété en aucune façon. En général, c'est une bonne pratique de toujours citer deux fois les noms de variables dans l'interpréteur de commandes.

59
répondu Josh Lee 2017-01-04 12:52:08

$BASH_SOURCE donne la bonne réponse lors de la recherche du script.

Cela inclut cependant le chemin pour obtenir le nom du fichier des scripts, utilisez:

$(basename $BASH_SOURCE) 
57
répondu Zainka 2014-10-29 11:58:41

si vous le voulez sans le chemin, alors vous utiliserez ${0##*/}

21
répondu Mr. Muskrat 2008-10-11 15:31:42

pour répondre À Chris Conway , sur Linux (au moins) vous voulez faire cela:

echo $(basename $(readlink -nf "151900920"))

readlink imprime la valeur d'un lien symbolique. Si ce n'est pas un lien symbolique, il imprime le nom de fichier. - n lui dit de ne pas imprimer une nouvelle ligne. -f lui dit de suivre le lien complètement (si un lien symbolique était un lien vers un autre lien, il résoudrait aussi celui-ci).

19
répondu Travis B. Hartwell 2017-05-23 12:10:54

j'ai trouvé que cette ligne fonctionne toujours, indépendamment du fait que le fichier soit fourni ou exécuté sous forme de script.

echo "${BASH_SOURCE[${#BASH_SOURCE[@]} - 1]}"

si vous voulez suivre symlinks utilisez readlink sur le chemin que vous obtenez ci-dessus, récursivement ou non-récursivement.

la raison pour laquelle les travaux à une seule doublure s'explique par l'utilisation de la variable d'environnement BASH_SOURCE et de son associée FUNCNAME .

BASH_SOURCE

une variable de tableau dont les membres sont les noms de fichier source où les noms de fonction de 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 à partir de ${BASH_SOURCE[$i+1]}.

FUNCNAME

une variable de tableau contenant les noms de toutes les fonctions shell actuellement dans la pile d'appels d'exécution. L'élément d'index 0 est le nom de toute en cours d'exécution de la fonction shell. L'élément le plus bas (celui dont l'indice est le plus élevé) est "main". Cette variable n'existe que lorsqu'une fonction shell est exécutée. Les affectations à FUNCNAME n'ont aucun effet et retourner un code d'erreur. Si FUNCNAME est désactivé, 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]}. L'appelant builtin affiche la pile d'appel à l'aide de cette information.

[Source: manuel Bash]

12
répondu gkb0986 2014-08-31 20:59:57

ces réponses sont correctes pour les cas qu'elles déclarent 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" (de sorte qu'il tourne dans le même shell). Dans ce cas, vous obtenez le 0 $du script d'appel. Et dans ce cas, je ne pense pas qu'il est possible d'obtenir le nom du script lui-même.

C'est un cas de bord et ne doit pas être pris trop au sérieux. Si vous exécutez le script depuis un autre script directement (sans'source')), utiliser 0 $marchera.

11
répondu Jim Dodd 2009-03-12 15:34:18

Re: Réponse de Tanktalus (acceptée) ci-dessus, une façon légèrement plus propre est d'utiliser:

me=$(readlink --canonicalize --no-newline "151900920")

si votre script provient d'un autre script bash, vous pouvez utiliser:

me=$(readlink --canonicalize --no-newline $BASH_SOURCE)

je suis d'accord qu'il serait déroutant de déréférencier les liens symboliques si votre objectif est de fournir une rétroaction à l'utilisateur, mais il y a des occasions où vous avez besoin d'obtenir le nom canonique à un script ou un autre fichier, et c'est la meilleure façon, imo.

8
répondu simon 2010-10-15 05:25:25

si vous invoquez le script shell comme

/home/mike/runme.sh

0 $ est le nom complet

 /home/mike/runme.sh

basename $0 obtiendra le nom du fichier de base

 runme.sh

et vous devez mettre ce nom de base dans une variable comme

filename=$(basename "151930920")

et ajouter votre texte supplémentaire

echo "You are running $filename"

donc vos scripts comme

/home/mike/runme.sh
#!/bin/bash 
filename=$(basename "151950920")
echo "You are running $filename"
6
répondu LawrenceLi 2017-01-25 02:50:44

vous pouvez utiliser $0 pour déterminer votre nom de script (avec le chemin complet) - pour obtenir le nom de script seulement vous pouvez couper cette variable avec

basename "151900920"
5
répondu VolkA 2008-10-10 17:24:20
this="$(dirname "$(realpath "$BASH_SOURCE")")"

ceci résout les liens symboliques (realpath fait cela), gère les espaces (guillemets doubles font cela), et trouvera le nom de script courant même s'il provient (. ./ myscript) ou appelé par d'Autres scripts ($BASH_SOURCE gère cela). Après tout cela, il est bon de sauvegarder ceci dans une variable d'environnement pour la réutiliser ou pour une copie facile ailleurs (ceci=)...

5
répondu jcalfee314 2012-11-14 16:28:35

puisque certains commentaires ont été demandés au sujet du nom de fichier sans extension, voici un exemple pour accomplir cela:

FileName=${0##*/}
FileNameWithoutExtension=${FileName%.*}

Profitez-en!

4
répondu Simon Mattes 2018-02-05 18:12:40

Info grâce à Bill Hernandez. J'ai ajouté des 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 ----------------------->         "
    echo "# $2 ----------------------->         "
    echo "# path to me --------------->  "151900920"     " | sed "s/$USER/$USER/g"
    echo "# parent path -------------->  ${0%/*}  " | sed "s/$USER/$USER/g"
    echo "# my name ------------------>  ${0##*/} "
    echo
}

Cheers

2
répondu linxuser 2015-02-22 06:50:03

dans bash vous pouvez obtenir le nom du fichier de script en utilisant " 151920920" . Généralement , etc sont d'accéder aux arguments CLI. De même " 151920920 " est d'accéder au nom qui déclenche le script(nom du fichier script).

#!/bin/bash
echo "You are running "151900920""
...
...

si vous invoquez le script avec le chemin comme /path/to/script.sh alors " 151920920 " donnera aussi le nom du fichier avec le chemin. Dans ce cas, vous devez utiliser $(basename "151980920") pour obtenir seulement le nom du fichier script.

2
répondu rashok 2018-04-10 14:42:38
echo "$(basename "`test -L ${BASH_SOURCE[0]} \
                   && readlink ${BASH_SOURCE[0]} \
                   || echo ${BASH_SOURCE[0]}`")"
1
répondu ecwpz91 2017-08-15 22:14:21

echo "Vous exécutez $0"

0
répondu mmacaulay 2008-10-10 17:23:19

"151910920" ne répond pas à la question (telle que je la comprends). Une démonstration:

$ cat script.sh
#! /bin/sh
echo `basename "151900920"`
$ ./script.sh 
script.sh
$ ln script.sh linktoscript
$ ./linktoscript 
linktoscript

Comment obtenir ./linktoscript pour imprimer script.sh ?

[MODIFIER] Par @ephemient dans les commentaires ci-dessus, bien que le lien symbolique chose peut sembler artificiel, il est possible de jouer avec les "151910920" , de sorte qu'il ne représente pas un système de fichiers de ressources. L'opération est un peu ambiguë sur ce qu'il voulait.

0
répondu Chris Conway 2008-10-10 21:13:41
DIRECTORY=$(cd `dirname "151900920"` && pwd)

j'ai obtenu ce qui précède d'une autre question de débordement de pile, un script Bash peut-il dire dans quel répertoire il est stocké? , mais je pense que c'est utile pour ce sujet aussi.

0
répondu Koter84 2017-05-23 11:33:25

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  ]
then
  val="*** Unknown  ***"
elif [ -n  ]
then
# otherwise make first arg as val
  val=
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
-5
répondu hynt 2015-04-16 10:32:16