Come trovare il file in cui è definita una funzione bash?


33

Non riesco a capire come trovare il file in cui è definita una funzione bash ( __git_ps1nel mio caso).

Ho sperimentato con declare, type, which, ma nulla mi dice che il file di origine. Ho letto da qualche parte che declarepuò stampare il nome del file e il numero di riga, ma non è stato spiegato come. La helppagina per declarenon lo dice neanche.

Come posso ottenere queste informazioni?


Se il percorso del file della funzione non è incluso in $PATH, typenon funzionerà. Potresti provare a usare solo findo locate. locatesarà molto più veloce, poiché utilizza un database preesistente, ma non funzionerà se il comando è stato installato solo di recente.
user628544

Risposte:


37

Se si è pronti per eseguire la funzione, è possibile ottenere le informazioni utilizzando set -xper tracciare l'esecuzione e impostare la PS4variabile.

  1. Inizia con bash --debuggeroppure usa shopt -s extdebugper registrare ulteriori informazioni di debug.

  2. Set PS4, il 'prompt' stampato durante la traccia per mostrare la linea di origine.

  3. Attiva la traccia.

  4. puoi quindi eseguire la tua funzione e per ogni riga otterrai il nome del file della funzione.

  5. utilizzare set +xper disattivare la traccia.

Quindi per questo caso corri

bash --debugger
PS4='+ ${BASH_SOURCE[0]} '
set -x ; __git_ps1 ; set +x

"-x Dopo aver espanso ogni comando semplice, per comando, caso comando, selezionare comando o aritmetica per comando, visualizza il valore espanso di PS4, seguito dal comando e dai suoi argomenti espansi o dall'elenco di parole associato." Bello!
20

25

Se non si desidera eseguire la funzione, è comunque possibile impostare il debug e ottenere le informazioni. I passaggi sono

  1. avviare bash --debuggero shopt -s extdebugprima che la funzione sia definita.
  2. declare -F __git_ps1

e riporterà dove è definita la funzione.

I vantaggi di questo metodo rispetto al vedere la traccia di esecuzione annotata con PS4 sono

  • Molto meno output
  • Risponde direttamente alla domanda

I vantaggi della traccia di esecuzione sono

  • Visualizza tutte le funzioni chiamate contemporaneamente
  • Vedi le relazioni tra le funzioni chiamate
  • Vedi ricorsione

Consiglio vivamente di avere shopt -s extdebugall'inizio di entrambi ~/.bashrce ~/.bash_profiledi coprire i diversi file utilizzati nei diversi casi di Invocazione .


1
Funziona anche se shopt -s extdebugviene chiamato dopo aver definito la funzione. Attenzione, i numeri di riga potrebbero essere disattivati ​​(un bug corrente) se la funzione viene dichiarata attraverso eval.
Stéphane Chazelas,

Ero dopo un completamento fuorviato per vpnc. Dopo che bash --debuggerdovevo effettivamente attivare il completamento per ottenere la funzione di completamento definita e ottenere da esso segnalato declare -F _vpnc.
Harald

Non ho ~/.bash_profilein Xubuntu 18.04.
Jarno

Perché consigliamo vivamente dishopt -s extdebug impostare come predefinito?
Jarno

@jarno Vedi la pagina del manuale, ma ti permette di vedere queste informazioni, consente di ereditare le trappole DEBUG e non ha alcun lato negativo per quanto posso vedere. Vedi il link per alternative a ~ / .bash_profile o semplicemente crealo.
Icaro

9

La grande soluzione di @ icarus funziona per le funzioni, purché siano definite letteralmente e non il risultato di uno evaldei contenuti di un altro file (in cui il file con evalverrà visualizzato come sorgente). Non stamperà il file sorgente di alias, built-in di shell (come echo) ed eseguibili (binari o meno) e credo che queste informazioni non siano disponibili in generale. Alcuni comandi potrebbero stampare i loro file sorgente (e potrebbero anche essere sinceri a riguardo), sia nel corso della normale esecuzione che in risposta a un segnale.

__git_ps1è definito in /usr/share/git/git-prompt.she /usr/share/git/completion/git-prompt.shsul mio sistema, Arch Linux, quindi potrebbe essere lo stesso per te.

Dai un'occhiata alla sezione Invocazione di man bashse vuoi cercare comandi specifici provenienti all'inizio della shell - potrebbero avere origine altri file che a loro volta generano altri file.


È possibile ottenere un elenco di file provenienti all'avvio bash?
pfnuesel,

@pfnuesel - dipende da te. I valori predefiniti sono dentro $HOME/.bashrce dentro $HOME/.profile. Vedi: linuxfromscratch.org/blfs/view/svn/postlfs/profile.html che spiega alcuni dei dettagli su quando e come ogni file proviene.
Joe,

2
@Joe gnu.org/software/bash/manual/html_node/Bash-Startup-Files.html è un riferimento molto migliore. /etc/profile, $HOME/.bash_profile, $HOME/.bash_login, E il contenuto di $ENVe $BASH_ENVnecessità di essere aggiunti alla vostra lista.
icarus

@icarus - Grazie. Questa è una spiegazione migliore.
Joe,

8

Non sembra possibile in bash, ma è in zsh:

$ type __git_ps1
> __git_ps1 is a shell function from /usr/share/git/git-prompt.sh

La domanda specifica bash ...
Jeff Schaller

4
@JeffSchaller: il modo più ovvio di usare questa risposta è impostare zsh per creare gli stessi file che bash farebbe, quindi usarlo per trovare la definizione. Questa risposta non suggerisce di passare a zsh, solo che è ovviamente uno strumento utile che capisce meglio la sintassi della shell rispetto a strumenti generici come find/ locate/ grep.
Peter Cordes,

Direi, quindi, @PeterCordes, che questa risposta attualmente non fa quello che dici che dovrebbe fare per rispondere alla domanda. Non so se zsh legge nativamente gli stessi file di bash.
Jeff Schaller

@JeffSchaller: concordato che questa risposta necessita di miglioramenti. zsh quasi certamente non legge gli stessi ~/.whateverfile di bash per impostazione predefinita e fornirà risposte utili solo per funzioni definite in posizioni condivise come in questo caso, che non sono ridefinite ~/.bashrco altro.
Peter Cordes,

-1

Dichiara una funzione con lo stesso nome e impostala il più presto possibile, quindi attiva la modalità xtrace, qualcosa del tipo:

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

Successivamente, quando effettui l'accesso, visualizzerai le informazioni di traccia che includono l'approvvigionamento di file. Nel momento in cui c'è un tentativo di dichiarazione della funzione di sola lettura esistente, verrà visualizzato un messaggio di errore. L'ultimo file di origine prima che dovrebbe contenere la dichiarazione che cerchi.

Potrebbe essere necessario inserirlo nel profilo bash del sistema. Ricorda anche di ripristinare le modifiche dopo aver trovato il colpevole.


-3

Hai provato questo?

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

o uno qualsiasi degli altri comandi trovati qui:

Come posso trovare tutti i file contenenti testo specifico su Linux? | Stack Overflow

Sembra che debba darti più di una spiegazione. La tua domanda chiede "" Pertanto, se si esegue il comando seguente, dovrebbe restituire tutti i file in cui è definita una funzione bash.

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

Programmazione BASH - Funzioni | Progetto di documentazione Linux


1
Link solo le risposte non sono assolutamente incoraggiate. Per favore, aggiungi qualche spiegazione.
Hememl
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.