¿Cómo encontrar el archivo donde se define una función bash?

33

No puedo entender cómo encontrar el archivo donde se define una función bash ( __git_ps1en mi caso).

Experimenté con declare, type, which, pero nada me dice que el archivo de origen. Leí en alguna parte que declarepuede imprimir el nombre del archivo y el número de línea, pero no se explicó cómo. La helppágina para declaretampoco lo dice.

¿Cómo puedo obtener esta información?

Alexey
fuente
Si la ruta al archivo de la función no está incluida $PATH, entonces typeno funcionará. Es posible que desee probar simplemente usando findo locate. locateserá mucho más rápido, ya que usa una base de datos preexistente, pero no funcionará si el comando se instaló recientemente.
user628544
Relacionado: unix.stackexchange.com/q/322459/117549
Jeff Schaller

Respuestas:

37

Si está preparado para ejecutar la función, puede obtener la información utilizando set -xpara rastrear la ejecución y establecer la PS4variable.

  1. Comience bash con --debuggero use shopt -s extdebugpara grabar información adicional de depuración.

  2. Establezca PS4, el 'aviso' impreso al rastrear para mostrar la línea de origen.

  3. Activa el rastreo.

  4. luego puede ejecutar su función y para cada línea obtendrá el nombre de archivo de la función.

  5. se usa set +xpara desactivar el rastreo.

Entonces para este caso correrás

bash --debugger
PS4='+ ${BASH_SOURCE[0]} '
set -x ; __git_ps1 ; set +x
Ícaro
fuente
"-x Después de expandir cada comando simple, para comando, comando de caso, comando de selección o aritmética para comando, muestre el valor expandido de PS4, seguido del comando y sus argumentos expandidos o la lista de palabras asociadas". ¡Agradable!
l0b0
25

Si no está dispuesto a ejecutar la función, aún puede configurar la depuración y obtener la información. Los pasos son

  1. iniciar bash --debuggero shopt -s extdebugantes de que se defina la función.
  2. declare -F __git_ps1

e informará dónde se define la función.

Las ventajas de este método en comparación con ver el seguimiento de ejecución anotado con PS4 son

  • Mucho menos rendimiento
  • Responde directamente la pregunta

Las ventajas de la traza de ejecución son

  • Ver todas las funciones llamadas a la vez
  • Ver las relaciones entre las funciones llamadas
  • Ver recursión

Recomiendo encarecidamente tener shopt -s extdebugal principio de ambos ~/.bashrcy ~/.bash_profilecubrir los diferentes archivos utilizados en diferentes casos de Invocación .

Ícaro
fuente
1
También funciona si shopt -s extdebugse llama después de definir la función. Tenga en cuenta que los números de línea pueden estar desactivados (un error actual) si la función se declara a través de eval.
Stéphane Chazelas
Estaba después de una finalización equivocada para vpnc. Después bash --debuggertuve que activar la finalización para definir la función de finalización y obtener un informe declare -F _vpnc.
Harald
9

La gran solución de @ icarus funciona para funciones, siempre que se definan literalmente y no el resultado de uno evalde los contenidos de otro archivo (en el que el archivo con el evalaparecerá como la fuente). No imprimirá el archivo fuente de alias, integraciones de shell (como echo) y ejecutables (binarios o no), y creo que esta información no está disponible en general. Algunos comandos pueden imprimir sus archivos fuente (e incluso pueden ser sinceros al respecto), ya sea en el curso de la ejecución normal o en respuesta a una señal.

__git_ps1está definido en /usr/share/git/git-prompt.shy /usr/share/git/completion/git-prompt.shen mi sistema, Arch Linux, por lo que puede ser lo mismo para usted.

Eche un vistazo a la sección Invocación de man bashsi desea buscar comandos específicamente originados al inicio del shell: pueden obtener otros archivos que a su vez obtienen otros archivos.

l0b0
fuente
¿Se puede obtener una lista de los archivos que se obtienen al comenzar bash?
pfnuesel
@pfnuesel: depende de ti. Los valores predeterminados son in $HOME/.bashrcy in $HOME/.profile. Consulte: linuxfromscratch.org/blfs/view/svn/postlfs/profile.html que explica algunos de los detalles de cuándo y cómo se obtiene cada archivo.
Joe
2
@Joe gnu.org/software/bash/manual/html_node/Bash-Startup-Files.html es una referencia mucho mejor. /etc/profile, $HOME/.bash_profile, $HOME/.bash_login, Y el contenido de $ENVy $BASH_ENVnecesidad de ser añadidos a la lista.
Ícaro
@icarus - Gracias. Esa es una mejor explicación.
Joe
8

No parece posible en bash, pero está en zsh:

$ type __git_ps1
> __git_ps1 is a shell function from /usr/share/git/git-prompt.sh
pfnuesel
fuente
La pregunta especifica bash ...
Jeff Schaller
44
@JeffSchaller: La forma obvia de usar esta respuesta es configurar zsh para que obtenga los mismos archivos que bash, y luego usarlo para encontrar la definición. Esta respuesta no sugiere cambiar a zsh, solo que obviamente es una herramienta útil que comprende la sintaxis de shell mejor que las herramientas genéricas como find/ locate/ grep.
Peter Cordes
Yo diría, entonces, @PeterCordes, que esta respuesta actualmente no hace lo que usted dice que debería hacer para responder la pregunta. No sé si zsh lee de forma nativa los mismos archivos que bash.
Jeff Schaller
@JeffSchaller: Estoy de acuerdo en que esta respuesta necesita mejorar. zsh casi seguramente no lee los mismos ~/.whateverarchivos que bash de manera predeterminada, y solo dará respuestas útiles para funciones definidas en ubicaciones compartidas como en este caso, que no se redefinen ~/.bashrcni nada .
Peter Cordes
-1

Declare una función con el mismo nombre y configúrela como de solo lectura lo antes posible, luego active el modo xtrace, algo así como:

__git_ps1(){ :;}
readonly -f __git_ps1
set -x

Después de eso, cuando inicie sesión, verá información de rastreo que incluye el abastecimiento de archivos. En el momento en que se intente declarar la función de solo lectura existente, verá un mensaje de error. El último archivo de origen antes de que contenga la declaración que busca.

Es posible que deba poner esto en el perfil de bash del sistema. También recuerde revertir los cambios después de encontrar al culpable.

Dios de madera
fuente
-3

¿Intentaste esto?

grep -rnw '/path/to/somewhere/' -e "pattern" 

o cualquiera de los otros comandos encontrados aquí:

¿Cómo encuentro todos los archivos que contienen texto específico en Linux? El | Desbordamiento de pila

Parece que necesito darte más explicaciones. Su pregunta es "" Por lo tanto, si ejecuta el siguiente comando, debería devolver todos los archivos donde se define una función bash.

grep -rnw 'Path2Search' -e "#!/bin/bash"

Programación BASH - Funciones | Proyecto de documentación de Linux

RadFox
fuente
1
Las respuestas de solo enlace no se recomiendan. Por favor agregue alguna explicación.
heemayl