it-swarm.dev

¿Cómo puedo saber el nombre del archivo de script en un script de Bash?

¿Cómo puedo determinar el nombre del archivo de script Bash dentro del propio script?

Como si mi script estuviera en el archivo runme.sh, ¿cómo lo haría para mostrar el mensaje "Usted está ejecutando runme.sh" sin codificarlo?

512
Ma99uS
me=`basename "$0"`

Para leer a través de un enlace simbólico.1, que generalmente no es lo que quieres (normalmente no quieres confundir al usuario de esta manera), prueba:

me="$(basename "$(test -L "$0" && readlink "$0" || echo "$0")")"

OMI, eso producirá resultados confusos. "Corrí foo.sh, pero está diciendo que estoy ejecutando bar.sh !? ¡Debe ser un error!" Además, uno de los propósitos de tener enlaces simbólicos con nombres diferentes es proporcionar una funcionalidad diferente basada en el nombre que se llama (piense gzip y gunzip en algunas plataformas).


1 Es decir, para resolver enlaces simbólicos de tal manera que cuando el usuario ejecuta foo.sh que en realidad es un enlace simbólico a bar.sh, desea utilizar el nombre resuelto bar.sh en lugar de foo.sh.

538
Tanktalus
 # ------------- 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
 
 # ---- --------- LLAMADO ------------- # 
 
 # Aviso en la siguiente línea, el primer argumento se llama dentro de double, 
 # y comillas simples, ya que contiene dos palabras 
 
 $ /misc/Shell_scripts/check_root/show_parms.sh "'hello there'" "'william'" 
 
 # ------------- RESULTADOS ------------- # 
 
 # argumentos llamados con ---> 'hola hay' 'william' 
 # $ 1 ----------------------> 'hola allí' 
 # $ 2 ----------------------> 'william' 
 # Ruta a mí ---------- ----> /misc/Shell_scripts/check_root/show_parms.sh[.____.◆# ruta principal -------------> /misc/Shell_scripts/check_root[.____.◆# mi nombre -----------------> show_parms.sh 
 
 # ------------- END --- ---------- # 
222
Bill Hernandez

Con bash> = 3 los siguientes trabajos:

$ ./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"
178
Dimitre Radoulov

Si el nombre del script tiene espacios en él, una forma más robusta es usar "$0" o "$(basename "$0")" - o en MacOS: "$(basename \"$0\")". Esto evita que el nombre se dañe o se interprete de cualquier manera. En general, es una buena práctica siempre citar los nombres de las variables en el Shell.

61
Josh Lee

$BASH_SOURCE da la respuesta correcta al obtener el script.

Sin embargo, esto incluye la ruta para obtener solo el nombre de archivo de los scripts, usar:

$(basename $BASH_SOURCE) 
59
Zainka

Si lo desea sin la ruta, entonces usaría ${0##*/}

23
Mr. Muskrat

Para responder a Chris Conway , en Linux (al menos) harías esto:

echo $(basename $(readlink -nf $0))

readlink imprime el valor de un enlace simbólico. Si no es un enlace simbólico, imprime el nombre del archivo. -n le dice que no imprima una nueva línea. -f le dice que siga el enlace completamente (si un enlace simbólico fuera un enlace a otro enlace, también lo resolvería).

19
Travis B. Hartwell

He encontrado que esta línea siempre funciona, independientemente de si el archivo se está obteniendo o se ejecuta como un script.

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

Si desea seguir los enlaces simbólicos, use readlink en la ruta que aparece arriba, recursivamente o no recursivamente.

La razón por la que funciona una línea se explica por el uso de la variable de entorno BASH_SOURCE y su asociada FUNCNAME.

BASH_SOURCE

Una variable de matriz cuyos miembros son los nombres de archivo de origen donde se definen los nombres de función de Shell correspondientes en la variable de matriz FUNCNAME. La función de shell $ {FUNCNAME [$ i]} se define en el archivo $ {BASH_SOURCE [$ i]} y se llama desde $ {BASH_SOURCE [$ i + 1]}.

Nombre de pila

Una variable de matriz que contiene los nombres de todas las funciones de Shell que se encuentran actualmente en la pila de llamadas de ejecución. El elemento con índice 0 es el nombre de cualquier función de Shell que se esté ejecutando actualmente. El elemento que está más abajo (el que tiene el índice más alto) es "main". Esta variable existe solo cuando se está ejecutando una función de Shell. Las asignaciones a FUNCNAME no tienen efecto y devuelven un estado de error. Si FUNCNAME no está configurado, pierde sus propiedades especiales, incluso si se reinicia posteriormente.

Esta variable se puede utilizar con BASH_LINENO y BASH_SOURCE. Cada elemento de FUNCNAME tiene elementos correspondientes en BASH_LINENO y BASH_SOURCE para describir la pila de llamadas. Por ejemplo, $ {FUNCNAME [$ i]} fue llamado desde el archivo $ {BASH_SOURCE [$ i + 1]} en la línea $ {BASH_LINENO [$ i]}. El integrante de la persona que llama muestra la pila de llamadas actual con esta información.

[Fuente: manual de Bash]

13
gkb0986

Estas respuestas son correctas para los casos que indican, pero aún existe un problema si ejecuta la secuencia de comandos desde otra secuencia de comandos con la palabra clave 'fuente' (para que se ejecute en el mismo Shell). En este caso, obtienes los $ 0 del script de llamada. Y en este caso, no creo que sea posible obtener el nombre del script en sí.

Este es un caso Edge y no debe tomarse TAMBIÉN seriamente. Si ejecuta el script desde otro script directamente (sin 'fuente'), el uso de $ 0 funcionará.

11
Jim Dodd

Re: la respuesta de Tanktalus (aceptada) arriba, una forma un poco más limpia es usar:

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

Si su script se ha obtenido de otro script de bash, puede usar:

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

Estoy de acuerdo en que sería confuso desreferenciar los enlaces simbólicos si su objetivo es proporcionar comentarios al usuario, pero hay ocasiones en las que necesita obtener el nombre canónico de un script u otro archivo, y esta es la mejor manera, imo.

8
simon

Dado que algunos comentarios preguntaron sobre el nombre de archivo sin extensión, aquí hay un ejemplo de cómo lograrlo:

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

¡Disfrutar!

8
Simon Mattes

si tu invocar shell script como

/home/mike/runme.sh

$ 0 es el nombre completo

 /home/mike/runme.sh

nombre base $ 0 obtendrá el nombre del archivo base

 runme.sh

y necesitas poner este nombre básico en una variable como

filename=$(basename $0)

y agrega tu texto adicional

echo "You are running $filename"

a tus scripts les gusta

/home/mike/runme.sh
#!/bin/bash 
filename=$(basename $0)
echo "You are running $filename"
8
LawrenceLi

Puede usar $ 0 para determinar el nombre de su script (con la ruta completa): para obtener el nombre del script solo puede recortar esa variable con

basename $0
7
VolkA
this="$(dirname "$(realpath "$BASH_SOURCE")")"

Esto resuelve los enlaces simbólicos (realpath lo hace), maneja los espacios (las comillas dobles lo hacen) y encontrará el nombre del script actual incluso cuando se obtenga (./myscript) o sea llamado por otros scripts ($ BASH_SOURCE lo maneja). Después de todo eso, es bueno guardar esto en una variable de entorno para reutilizarlo o para copiarlo fácilmente en otro lugar (esto =) ...

5
jcalfee314

En bash puede obtener el nombre del archivo de script utilizando $0. En general, $1, $2 etc son para acceder a los argumentos de la CLI. De manera similar, $0 es acceder al nombre que activa el script (nombre del archivo de script).

#!/bin/bash
echo "You are running $0"
...
...

Si invocas el script con la ruta como /path/to/script.sh, entonces $0 también le dará el nombre del archivo con la ruta. En ese caso, debe usar $(basename $0) para obtener solo el nombre del archivo de script.

3
rashok

Información gracias a Bill Hernández. He añadido algunas preferencias que estoy adoptando.

#!/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
}

Aclamaciones

2
linxuser
echo "$(basename "`test -L ${BASH_SOURCE[0]} \
                   && readlink ${BASH_SOURCE[0]} \
                   || echo ${BASH_SOURCE[0]}`")"
1
ecwpz91

$0 no responde la pregunta (como yo la entiendo). Una demostración:

 $ cat script.sh 
 #! /bin/sh[.____.◆echo `nombre base $ 0` 
 $ ./script.sh 
 script.sh 
 $ ln script.sh linktoscript 
 $ ./linktoscript 
 linktoscript 

¿Cómo se consigue que ./linktoscript imprima script.sh?

[EDITAR] Según @ephemient en los comentarios anteriores, aunque el enlace simbólico puede parecer ideado, es posible jugar con $0 de manera que no represente un recurso del sistema de archivos. El OP es un poco ambiguo sobre lo que quería.

1
Chris Conway

Aquí está lo que se me ocurrió, inspirado en Dimitre Radoulov 's respuesta (que por cierto, he votado) .

script="$BASH_SOURCE"
[ -z "$BASH_SOURCE" ] && script="$0"

echo "Called $script with $# argument(s)"

independientemente de la forma en que llames a tu guión

. path/to/script.sh

o

./path/to/script.sh
0
Salathiel Genèse

echo "estas corriendo $ 0"

0
mmacaulay
DIRECTORY=$(cd `dirname $0` && pwd)

Obtuve lo anterior de otra pregunta de desbordamiento de pila,¿Puede un script de Bash indicar en qué directorio está almacenado?, pero creo que también es útil para este tema.

0
Koter84