¿Cómo sé el nombre del archivo de script en un script Bash?


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

Al igual que si mi script está en el archivo runme.sh, entonces ¿cómo lo haría para mostrar "Se está ejecutando runme.sh" mensaje sin codificar eso?

Author: Peter Mortensen, 2008-10-10

21 answers

me=`basename "$0"`

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

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

IMO, eso producirá una salida confusa. "Corrí foo.sh pero está diciendo que estoy corriendo bar.sh ¡Debe ser un bicho!"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 como (piense en gzip y gunzip en algunas plataformas).

 474
Author: Tanktalus,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-04-28 21:04:04
# ------------- 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

# ------------- 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'
# $1 ---------------------->  'hello there'
# $2 ---------------------->  '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
Author: Bill Hernandez,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-08-28 00:41:47

Con bash >= 3 las siguientes obras:

$ ./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"
 160
Author: Dimitre Radoulov,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-10-24 18:50:00

Si el nombre del script tiene espacios, una forma más robusta es usar "$0" o "$(basename "$0")" - o en macOS: "$(basename \"$0\")". Esto evita que el nombre sea mutilado o interpretado de alguna manera. En general, es una buena práctica citar siempre los nombres de las variables en el shell.

 59
Author: Josh Lee,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-01-04 12:52:08

$BASH_SOURCE da la respuesta correcta al obtener el script.

Sin embargo, esto incluye la ruta, por lo que para obtener solo el nombre del archivo de scripts, use:

$(basename $BASH_SOURCE) 
 57
Author: Zainka,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-10-29 11:58:41

Si lo quieres sin la ruta entonces usarías ${0##*/}

 21
Author: Mr. Muskrat,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-10-11 15:31:42

Para responder Chris Conway , en Linux (al menos) usted haría 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 resolvería ese enlace).

 19
Author: Travis B. Hartwell,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:10:54

He encontrado que esta línea siempre funciona, independientemente de si el archivo está siendo originado o ejecutado como un script.

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

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

La razón por la que el one-liner funciona 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 la función shell correspondiente se definen nombres en la variable FUNCNAME array. La función shell ${FUNCNAME[$i]} está definida en el archivo ${BASH_SOURCE[$i]} y llamó desde ${BASH_SOURCE[$i+1]}.

FUNCNAME

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

Esta variable se puede usar 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 el número de línea ${BASH_LINENO[$i]}. El caller builtin muestra la pila de llamadas actual usando esta información.

[Fuente: Manual de Bash]

 12
Author: gkb0986,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-08-31 20:59:57

Estas respuestas son correctas para los casos que indican, pero todavía hay un problema si ejecuta el script desde otro script utilizando la palabra clave 'source' (de modo que se ejecute en el mismo shell). En este caso, se obtiene el script 0 del script de llamada. Y en este caso, no creo que sea posible obtener el nombre del guion en sí.

Este es un caso extremo y no debe tomarse DEMASIADO en serio. Si ejecuta el script desde otro script directamente (sin 'source'), usando $0 trabajo.

 11
Author: Jim Dodd,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-03-12 15:34:18

Re: Respuesta de Tanktalus (aceptada) arriba, una forma ligeramente más limpia es usar:

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

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

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

Estoy de acuerdo en que sería confuso desreferenciar enlaces simbólicos si su objetivo es proporcionar retroalimentación 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
Author: simon,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-10-15 05:25:25

Si invoca el script de shell como

/home/mike/runme.sh

$0 es el nombre completo

 /home/mike/runme.sh

Basename Bas 0 obtendrá el nombre del archivo base

 runme.sh

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

filename=$(basename $0)

Y añade tu texto adicional

echo "You are running $filename"

Así que sus scripts como

/home/mike/runme.sh
#!/bin/bash 
filename=$(basename $0)
echo "You are running $filename"
 6
Author: LawrenceLi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-01-25 02:50:44

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
 5
Author: VolkA,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-10-10 17:24:20
this="$(dirname "$(realpath "$BASH_SOURCE")")"

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

 5
Author: jcalfee314,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-11-14 16:28:35

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

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

Disfrute!

 4
Author: Simon Mattes,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-02-05 18:12:40

Info 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
}

Salud

 2
Author: linxuser,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-02-22 06:50:03

En bash puede obtener el nombre del archivo de script usando $0. En general $1, $2 etc son para acceder a los argumentos CLI. Del mismo modo $0 es acceder al nombre que desencadena el script (nombre del archivo script).

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

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

 2
Author: rashok,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-04-10 14:42:38
echo "$(basename "`test -L ${BASH_SOURCE[0]} \
                   && readlink ${BASH_SOURCE[0]} \
                   || echo ${BASH_SOURCE[0]}`")"
 1
Author: ecwpz91,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-08-15 22:14:21

Echo "Estás corriendo 0 0"

 0
Author: mmacaulay,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-10-10 17:23:19

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

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

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

[EDITAR] Per @ephemient en los comentarios anteriores, aunque el enlace simbólico puede parecer artificial, es posible jugar con $0 de manera que no represente un recurso del sistema de archivos. La OPERACIÓN es un poco ambigua sobre lo que quería.

 0
Author: Chris Conway,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-10-10 21:13:41
DIRECTORY=$(cd `dirname $0` && pwd)

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

 0
Author: Koter84,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 11:33:25

¿Algo así?

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
 -5
Author: hynt,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-04-16 10:32:16