OMI, eso producirá resultados confusos. "Ejecuté 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 le llama (piense en gzip y gunzip en algunas plataformas).
1 Es decir, para resolver enlaces simbólicos de modo que cuando el usuario ejecuta, foo.shque en realidad es un enlace simbólico bar.sh, desea utilizar el nombre resuelto en bar.shlugar de foo.sh.
-1, 1. readlink solo viajará un enlace simbólico profundo, 2. $0en el primer ejemplo está sujeto a la división de palabras, 3. $0se pasa a basename, readlink y echo en una posición que le permita ser tratado como un interruptor de línea de comando . Sugiero lugar me=$(basename -- "$0")o mucho más eficiente a expensas de la legibilidad, me=${0##*/}. Para enlaces simbólicos, me=$(basename -- "$(readlink -f -- "$0")")suponiendo utilidades gnu, de lo contrario será un script muy largo que no escribiré aquí.
Score_Under
246
# ------------- 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 ------------- ## ------------- LLAMADO ------------- #
# Aviso en la siguiente línea, el primer argumento se llama dentro del doble, # Aviso en la siguiente línea, el primer argumento se llama dentro del doble,
# y comillas simples, ya que contiene dos palabras# y comillas simples, ya que contiene dos palabras$ /misc/shell_scripts/check_root/show_parms.sh "'hola allí'" "'william'"/ misc / shell_scripts / check_root / show_parms . sh "'hola' '" "' william '"
# ------------- RESULTADOS ------------- ## ------------- RESULTADOS ------------- #
# argumentos llamados con ---> 'hola' 'william'# argumentos llamados con ---> 'hola' 'william'
# $ 1 ----------------------> 'hola'# $ 1 ----------------------> 'hola'
# $ 2 ----------------------> 'william'# $ 2 ----------------------> 'william'
# ruta hacia mí --------------> /misc/shell_scripts/check_root/show_parms.sh# ruta hacia mí --------------> /misc/shell_scripts/check_root/show_parms.sh
# ruta principal -------------> / misc / shell_scripts / check_root# ruta principal -------------> / misc / shell_scripts / check_root
# mi nombre -----------------> show_parms.sh# mi nombre -----------------> show_parms.sh
# ------------- FIN ------------- ## ------------- FIN ------------- #
¿Cómo obtengo solo show_params, es decir, el nombre sin ninguna extensión opcional?
Acumenus
No funciona en caso de que el script se invoque desde otra carpeta. La ruta está incluida en el ${0##*/}. Probado con GitBash.
AlikElzin-kilaka
1
Lo anterior no funcionó para mí desde un script .bash_login, pero la solución Dimitre Radoulov de $ BASH_SOURCE funciona muy bien.
John
@ John Seguramente te refieres a .bash_profile ? O alternativamente .bashrc ? Sin embargo, debe saber que hay algunas diferencias sutiles en cómo se invocan / obtienen. Estoy muerto de cansancio, pero si lo estoy pensando bien, probablemente sea el problema. Un lugar importante es si está iniciando sesión en un sistema de forma remota a través de, por ejemplo, ssh versus en el sistema local.
Pryftan
193
Con bash> = 3, los siguientes trabajos:
$ ./s0 is:./s
BASH_SOURCE is:./s
$ ../s0 is: bash
BASH_SOURCE is:./s
$ cat s#!/bin/bash
printf '$0 is: %s\n$BASH_SOURCE is: %s\n'"$0""$BASH_SOURCE"
¡Excelente! Esa es la respuesta que funciona tanto para ./scrip.sh como para fuente ./script.sh
zhaorufei
44
Esto es lo que quiero, y es fácil usar " dirname $BASE_SOURCE" para obtener el directorio que ubicaron los scripts.
Larry Cai
2
Casi aprendí esa diferencia de la manera más difícil cuando escribí un script de eliminación automática. Afortunadamente, 'rm' tenía el alias de 'rm -i' :)
kervin
de todos modos a la. ./s para obtener el nombre ./s en lugar de bash? He descubierto que $ 1 no siempre se establece en ./s ...
David Mokon Bond
1
Está en BASH_SOURCE , ¿no?
Dimitre Radoulov
69
$BASH_SOURCE da la respuesta correcta al obtener el script.
Sin embargo, esto incluye la ruta, así que para obtener solo el nombre de archivo de los scripts, use:
Esta respuesta es, en mi humilde opinión, la mejor porque la solución hace uso del código de autodocumentación. $ BASH_SOURCE es totalmente comprensible sin leer ninguna documentación, mientras que $ {0 ## * /} no lo es
Andreas M. Oberheim el
Esta respuesta es de más valor, creo, porque si corremos como . <filename> [arguments], $0daría el nombre del llamador de shell. Bueno, al menos en OSX seguro.
Mihir
68
Si el nombre del script tiene espacios en él, de una manera más sólida es utilizar "$0"o "$(basename "$0")"- o en MacOS: "$(basename \"$0\")". Esto evita que el nombre sea destrozado o interpretado de ninguna manera. En general, es una buena práctica siempre entre comillas dobles nombres de variables en el shell.
¿Y si lo quiero sin ninguna extensión de archivo opcional?
Acumenus
Para eliminar una extensión, puede probar "$ {VARIABLE% .ext}" donde VARIABLE es el valor que obtuvo de $ {0 ## * /} y ".ext" es la extensión que desea eliminar.
BrianV
19
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 por completo (si un enlace simbólico fuera un enlace a otro enlace, también resolvería ese enlace).
-n es inofensivo pero no necesario porque la estructura $ (...) lo recortará.
zhaorufei
16
He encontrado que esta línea siempre funciona, independientemente de si el archivo se obtiene o se ejecuta como un script.
echo "${BASH_SOURCE[${#BASH_SOURCE[@]} - 1]}"
Si desea seguir el uso de enlaces simbólicos readlinken la ruta que obtiene arriba, recursivamente o no recursivamente.
La razón por la que funciona One-liner se explica por el uso de la BASH_SOURCEvariable de entorno y su asociado FUNCNAME.
BASH_SOURCE
Una variable de matriz cuyos miembros son los nombres de los archivos de origen donde se definen los nombres de funciones 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]}.
FUNCNAME
Una variable de matriz que contiene los nombres de todas las funciones de shell 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 más inferior (el que tiene el índice más alto) es "principal". Esta variable existe solo cuando se ejecuta 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 restablece posteriormente.
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]} se llamó desde el archivo $ {BASH_SOURCE [$ i + 1]} en el número de línea $ {BASH_LINENO [$ i]}. La persona que llama muestra la pila de llamadas actual con esta información.
Funciona si se origina en el archivo a (se supone que ael contenido es echo "${BASH_SOURCE[${#BASH_SOURCE[@]} - 1]}") de una sesión interactiva, entonces le dará ala ruta. Pero si escribe un script bcon source aél y lo ejecuta ./b, devolverá bla ruta.
PSkocik
12
Estas respuestas son correctas para los casos que indican, pero aún existe un problema si ejecuta el script desde otro script utilizando la palabra clave 'source' (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 marginal y no debe tomarse DEMASIADO en serio. Si ejecuta el script desde otro script directamente (sin 'fuente'), usar $ 0 funcionará.
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, en mi opinión.
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 lo llaman otros scripts ($ BASH_SOURCE maneja eso). Después de todo eso, es bueno guardar esto en una variable de entorno para reutilizarlo o copiarlo fácilmente en otro lugar (esto =) ...
FYI realpathno es un comando BASH incorporado. Es un ejecutable independiente que solo está disponible en ciertas distribuciones
StvnW
4
En bashpuede obtener el nombre del archivo de script utilizando $0. Generalmente $1, $2etc. son para acceder a los argumentos de la CLI. Del mismo modo $0es acceder al nombre que desencadena el script (nombre del archivo de script).
#!/bin/bash
echo "You are running $0"......
Si invoca el script con una ruta como, /path/to/script.shentonces $0tambié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.
[EDITAR] Según @ephemient en los comentarios anteriores, aunque el enlace simbólico puede parecer artificial, es posible jugar con él de $0tal manera que no represente un recurso del sistema de archivos. El OP es un poco ambiguo sobre lo que quería.
agregué una respuesta a esto a mi respuesta anterior, pero no estoy de acuerdo con que esto sea lo que realmente se quiere (o que usted debería querer, salvo algunas circunstancias atenuantes que actualmente no puedo entender)
Tanktalus
2
Creo que imprimir linktoscript en lugar de script.sh es una característica, no un error. Varios comandos de Unix usan su nombre para alterar su comportamiento. Un ejemplo es vi / ex / view.
mouviciel
@Tanktalus: Hay casos en los que desea que el comportamiento cambie en función de la ubicación real del archivo: en un proyecto anterior tenía un script de "Rama activa", que enlazaría varias rutas desde la rama en la que estaba. trabajando en; esas herramientas podrían averiguar en qué directorio se habían desprotegido para ejecutar los archivos correctos.
Andrew Aylett
2
Información gracias a Bill Hernández. Agregué algunas preferencias que estoy adoptando.
#!/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
}
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
Respuestas:
Para leer un enlace simbólico 1 , que generalmente no es lo que desea (por lo general, no desea confundir al usuario de esta manera), intente:
OMI, eso producirá resultados confusos. "Ejecuté 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 le llama (piense en gzip y gunzip en algunas plataformas).
1 Es decir, para resolver enlaces simbólicos de modo que cuando el usuario ejecuta,
foo.sh
que en realidad es un enlace simbólicobar.sh
, desea utilizar el nombre resuelto enbar.sh
lugar defoo.sh
.fuente
$0
en el primer ejemplo está sujeto a la división de palabras, 3.$0
se pasa a basename, readlink y echo en una posición que le permita ser tratado como un interruptor de línea de comando . Sugiero lugarme=$(basename -- "$0")
o mucho más eficiente a expensas de la legibilidad,me=${0##*/}
. Para enlaces simbólicos,me=$(basename -- "$(readlink -f -- "$0")")
suponiendo utilidades gnu, de lo contrario será un script muy largo que no escribiré aquí.fuente
show_params
, es decir, el nombre sin ninguna extensión opcional?${0##*/}
. Probado con GitBash.Con bash> = 3, los siguientes trabajos:
fuente
dirname $BASE_SOURCE
" para obtener el directorio que ubicaron los scripts.$BASH_SOURCE
da la respuesta correcta al obtener el script.Sin embargo, esto incluye la ruta, así que para obtener solo el nombre de archivo de los scripts, use:
fuente
. <filename> [arguments]
,$0
daría el nombre del llamador de shell. Bueno, al menos en OSX seguro.Si el nombre del script tiene espacios en él, de una manera más sólida es utilizar
"$0"
o"$(basename "$0")"
- o en MacOS:"$(basename \"$0\")"
. Esto evita que el nombre sea destrozado o interpretado de ninguna manera. En general, es una buena práctica siempre entre comillas dobles nombres de variables en el shell.fuente
Si lo quieres sin la ruta, entonces usarías
${0##*/}
fuente
Para responder a Chris Conway , en Linux (al menos) harías esto:
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 por completo (si un enlace simbólico fuera un enlace a otro enlace, también resolvería ese enlace).
fuente
He encontrado que esta línea siempre funciona, independientemente de si el archivo se obtiene o se ejecuta como un script.
Si desea seguir el uso de enlaces simbólicos
readlink
en la ruta que obtiene arriba, recursivamente o no recursivamente.La razón por la que funciona One-liner se explica por el uso de la
BASH_SOURCE
variable de entorno y su asociadoFUNCNAME
.[Fuente: manual de Bash]
fuente
a
(se supone quea
el contenido esecho "${BASH_SOURCE[${#BASH_SOURCE[@]} - 1]}"
) de una sesión interactiva, entonces le daráa
la ruta. Pero si escribe un scriptb
consource a
él y lo ejecuta./b
, devolveráb
la ruta.Estas respuestas son correctas para los casos que indican, pero aún existe un problema si ejecuta el script desde otro script utilizando la palabra clave 'source' (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 marginal y no debe tomarse DEMASIADO en serio. Si ejecuta el script desde otro script directamente (sin 'fuente'), usar $ 0 funcionará.
fuente
Dado que algunos comentarios preguntaron sobre el nombre de archivo sin extensión, aquí hay un ejemplo de cómo lograrlo:
¡Disfrutar!
fuente
Re: Respuesta de Tanktalus (aceptada) arriba, una forma un poco más limpia es usar:
Si su script proviene de otro script bash, puede usar:
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, en mi opinión.
fuente
source
nombres de script d.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
fuente
si su invocar shell script como
$ 0 es el nombre completo
basename $ 0 obtendrá el nombre del archivo base
y necesitas poner este nombre básico en una variable como
y agrega tu texto adicional
así que a tus guiones les gusta
fuente
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 lo llaman otros scripts ($ BASH_SOURCE maneja eso). Después de todo eso, es bueno guardar esto en una variable de entorno para reutilizarlo o copiarlo fácilmente en otro lugar (esto =) ...
fuente
realpath
no es un comando BASH incorporado. Es un ejecutable independiente que solo está disponible en ciertas distribucionesEn
bash
puede obtener el nombre del archivo de script utilizando$0
. Generalmente$1
,$2
etc. son para acceder a los argumentos de la CLI. Del mismo modo$0
es acceder al nombre que desencadena el script (nombre del archivo de script).Si invoca el script con una 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.fuente
fuente
$0
no responde la pregunta (según tengo entendido). Una demostración:¿Cómo se
./linktoscript
imprimescript.sh
?[EDITAR] Según @ephemient en los comentarios anteriores, aunque el enlace simbólico puede parecer artificial, es posible jugar con él de
$0
tal manera que no represente un recurso del sistema de archivos. El OP es un poco ambiguo sobre lo que quería.fuente
Información gracias a Bill Hernández. Agregué algunas preferencias que estoy adoptando.
Salud
fuente
Corto, claro y simple, en
my_script.sh
Fuera puesto:
fuente
Obtuve lo anterior de otra pregunta de Stack Overflow, ¿Puede un script Bash decir en qué directorio está almacenado? , pero creo que también es útil para este tema.
fuente
Esto es lo que se me ocurrió, inspirado en la respuesta de Dimitre Radoulov (que, por cierto, he votado) .
independientemente de la forma en que llame a su script
o
fuente
echo "Estás ejecutando $ 0"
fuente
¿Algo así?
fuente