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:
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.shqui est en fait un lien symbolique vers bar.sh, vous souhaitez utiliser le nom résolu bar.shplutôt que foo.sh.
-1, 1. readlink ne parcourra qu'un seul lien symbolique en profondeur, 2. $0dans le premier exemple est sujet à la séparation des mots, 3. $0est 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.
Score_Under
246
# ------------- 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 ------------- #
Comment puis-je obtenir juste show_params, c'est-à-dire le nom sans extension facultative?
Acumenus
Ne fonctionne pas si le script est appelé à partir d'un autre dossier. Le chemin est inclus dans le ${0##*/}. Testé à l'aide de GitBash.
AlikElzin-kilaka du
1
Ce qui précède n'a pas fonctionné pour moi à partir d'un script .bash_login, mais la solution Dimitre Radoulov de $ BASH_SOURCE fonctionne très bien.
John
@John Vous voulez sûrement dire .bash_profile ? Ou alternativement .bashrc ? Vous devez savoir cependant qu'il existe des différences subtiles dans la façon dont elles sont invoquées / obtenues. Je suis fatigué, mais si je pense bien, ce serait probablement le problème. Il est important de savoir si vous vous connectez à un système à distance, par exemple via ssh par rapport au système local.
Pryftan
193
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"
Cette réponse est à mon humble avis la meilleure parce que la solution utilise du code auto-documenté. $ BASH_SOURCE est totalement compréhensible sans lire aucune documentation alors que par exemple $ {0 ## * /} ne l'est pas
Andreas M. Oberheim
Cette réponse a plus de valeur si je crois parce que si nous courons comme . <filename> [arguments], $0donnerait le nom du shell de l'appelant. Bien au moins sur OSX, c'est sûr.
Mihir
68
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.
Et si je le veux sans extension de fichier optionnelle?
Acumenus
Pour supprimer une extension, vous pouvez essayer "$ {VARIABLE% .ext}" où VARIABLE est la valeur que vous avez obtenue de $ {0 ## * /} et ".ext" est l'extension que vous souhaitez supprimer.
BrianV
19
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).
-n est inoffensif mais pas nécessaire car la structure $ (...) le coupera.
zhaorufei
16
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 readlinksur 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_SOURCEvariable 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.
Cela fonctionne si vous sourcez dans un fichier a (supposons que ale contenu est echo "${BASH_SOURCE[${#BASH_SOURCE[@]} - 1]}") à partir d'une session interactive - alors il vous donnera ale chemin. Mais si vous écrivez un script bavec source aet que vous l'exécutez ./b, il retournera ble chemin d'accès.
PSkocik
12
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.
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.
Vous pouvez utiliser $ 0 pour déterminer le nom de votre script (avec le chemin complet) - pour obtenir le nom du script uniquement, vous pouvez couper cette variable avec
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 =) ...
FYI realpathn'est pas une commande BASH intégrée. Il s'agit d'un exécutable autonome qui n'est disponible que dans certaines distributions
StvnW
4
Dans bashvous pouvez obtenir le nom du fichier de script en utilisant $0. Généralement $1, $2etc sont pour accéder aux arguments CLI. Il en va de même $0pour 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.shalors, vous $0obtiendrez également le nom de fichier avec path. Dans ce cas, vous devez utiliser $(basename $0)pour obtenir uniquement le nom du fichier de script.
$0ne 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 ./linktoscriptimprimer script.sh?
[EDIT] Par @ephemient dans les commentaires ci-dessus, bien que le lien symbolique puisse sembler artificiel, il est possible de jouer avec $0tel qu'il ne représente pas une ressource de système de fichiers. L'OP est un peu ambigu sur ce qu'il voulait.
a ajouté une réponse à ma réponse ci-dessus, mais je ne suis pas d'accord pour dire que c'est ce qui est vraiment souhaité (ou que vous devriez le vouloir, sauf circonstances atténuantes que je ne peux pas actuellement comprendre)
Tanktalus
2
Je pense que l'impression de linktoscript au lieu de script.sh est une fonctionnalité, pas un bug. Plusieurs commandes Unix utilisent leur nom pour modifier leur comportement. Un exemple est vi / ex / view.
mouviciel
@Tanktalus: Il y a des cas où vous voulez que le comportement change en fonction de l'emplacement réel du fichier - sur un projet précédent, j'avais un script "Active branch", qui créerait un lien symbolique vers le chemin d'accès à plusieurs outils de la branche où j'étais travaille sur; ces outils pourraient alors découvrir dans quel répertoire ils avaient été extraits pour s'exécuter sur les bons fichiers.
Andrew Aylett
2
Info grâce à Bill Hernandez. J'ai ajouté quelques préférences que j'adopte.
#!/bin/bashfunctionUsage(){
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
}
N'est pas un script bash, c'est le chemin complet.
e-info128
-6
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
fiif[ $ans = n -o $ans = N -o $ans = no -o $ans =No-o $ans = NO ]then
echo "'no'"fireturn $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 Unknownif[-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 rentalcase $val in"trash") start_trash ;;"help") start_help ;;"www") firefox $homepage ;;*) echo "Sorry, I can not get a $val for you!";;esac# Case stop
Réponses:
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:
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 versbar.sh
, vous souhaitez utiliser le nom résolubar.sh
plutôt quefoo.sh
.la source
$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ôtme=$(basename -- "$0")
ou beaucoup plus efficace au détriment de la lisibilité,me=${0##*/}
. Pour les liens symboliques, enme=$(basename -- "$(readlink -f -- "$0")")
supposant les utils gnu, sinon ce sera un script très long que je n'écrirai pas ici.la source
show_params
, c'est-à-dire le nom sans extension facultative?${0##*/}
. Testé à l'aide de GitBash.Avec bash> = 3 les travaux suivants:
la 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:
la 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.la source
Si vous le souhaitez sans le chemin, vous utiliserez
${0##*/}
la source
Pour répondre à Chris Conway , sur Linux (au moins), vous feriez ceci:
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).
la source
J'ai trouvé que cette ligne fonctionnait toujours, que le fichier soit d'origine ou exécuté en tant que script.
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
.[Source: manuel Bash]
la source
a
(supposons quea
le contenu estecho "${BASH_SOURCE[${#BASH_SOURCE[@]} - 1]}"
) à partir d'une session interactive - alors il vous donneraa
le chemin. Mais si vous écrivez un scriptb
avecsource a
et que vous l'exécutez./b
, il retournerab
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.
la source
Étant donné que certains commentaires portaient sur le nom de fichier sans extension, voici un exemple comment y parvenir:
Prendre plaisir!
la source
Re: Réponse de Tanktalus (acceptée) ci-dessus, une manière légèrement plus propre consiste à utiliser:
Si votre script provient d'un autre script bash, vous pouvez utiliser:
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.
la source
source
noms de script d.Vous pouvez utiliser $ 0 pour déterminer le nom de votre script (avec le chemin complet) - pour obtenir le nom du script uniquement, vous pouvez couper cette variable avec
la source
si votre script shell d'invocation comme
$ 0 est le nom complet
nom de base $ 0 obtiendra le nom du fichier de base
et vous devez mettre ce nom de base dans une variable comme
et ajoutez votre texte supplémentaire
donc vos scripts comme
la 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 =) ...
la source
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 distributionsDans
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).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.la source
la source
$0
ne répond pas à la question (si je comprends bien). Une démonstration:Comment
./linktoscript
imprimerscript.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.la source
Info grâce à Bill Hernandez. J'ai ajouté quelques préférences que j'adopte.
À votre santé
la source
Court, clair et simple, en
my_script.sh
Production:
la source
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.
la source
Voici ce que je suis venu avec, inspiré par Dimitre Radoulov réponse de (que j'upvoted, par la voie) .
quelle que soit la façon dont vous appelez votre script
ou
la source
echo "Vous exécutez $ 0"
la source
quelque chose comme ça?
la source