Como encontrar o arquivo onde uma função bash é definida?

27

Não consigo descobrir como encontrar o arquivo no qual uma função bash está definida ( __git_ps1 no meu caso).

Eu experimentei com declare , type , which , mas nada me diz o arquivo de origem. Eu li em algum lugar que declare pode imprimir o nome do arquivo e o número da linha, mas não foi explicado como. A página help para declare também não diz.

Como posso obter essa informação?

    
por Alexey 12.11.2016 / 17:16

6 respostas

31

Se você estiver preparado para executar a função, poderá obter as informações usando set -x para rastrear a execução e configurar a variável PS4 .

  1. Inicie o bash com --debugger ou use shopt -s extdebug para registrar informações extras de depuração.

  2. Defina PS4 , o 'prompt' impresso durante o rastreamento para mostrar a linha de origem.

  3. Ativar rastreio.

  4. você pode então executar sua função e para cada linha você obterá o nome do arquivo da função.

  5. use set +x para desativar o rastreamento.

Então, para este caso, você executaria

bash --debugger
PS4='+ ${BASH_SOURCE[0]} '
set -x ; __git_ps1 ; set +x
    
por 12.11.2016 / 17:44
20

Se você não estiver disposto a executar a função, ainda poderá configurar a depuração e obter as informações. As etapas são

  1. inicie bash --debugger ou shopt -s extdebug antes de a função ser definida.
  2. declare -F __git_ps1

e informará onde a função está definida.

As vantagens deste método em comparação com a visualização do rastreio de execução anotado com o PS4 são

  • Muito menos saída
  • Responde diretamente à pergunta

As vantagens do rastreamento de execução são

  • Ver todas as funções chamadas de uma só vez
  • Veja as relações entre as funções chamadas
  • Ver recursão

Eu strongmente recomendo ter shopt -s extdebug no início de ambos ~/.bashrc e ~/.bash_profile para cobrir os diferentes arquivos usados em diferentes Invocação casos.

    
por 13.11.2016 / 00:55
9

A excelente solução da @ icarus funciona para funções, contanto que sejam definidas literalmente e não o resultado de um eval do conteúdo de outro arquivo (no qual o arquivo com eval aparecerá como a origem). Ele não imprimirá o arquivo de origem dos aliases, internos do shell (como echo ) e executáveis (binários ou não), e acredito que essas informações não estejam disponíveis em geral. Alguns comandos podem imprimir seus arquivos de origem (e podem até ser verdadeiros sobre isso), seja no decorrer da execução normal ou em resposta a um sinal.

__git_ps1 está definido em /usr/share/git/git-prompt.sh e /usr/share/git/completion/git-prompt.sh no meu sistema, Arch Linux, então pode ser o mesmo para você.

Dê uma olhada na seção Invocation de man bash se você quiser procurar comandos especificamente originados no início do shell - eles podem obter outros arquivos que, por sua vez, originam outros arquivos.

    
por 12.11.2016 / 17:37
8

Não parece ser possível em bash , mas está em zsh :

$ type __git_ps1
> __git_ps1 is a shell function from /usr/share/git/git-prompt.sh
    
por 12.11.2016 / 17:44
-1

Declare uma função com o mesmo nome e defina-a somente para leitura o mais cedo possível, depois ative o modo xtrace, algo como:

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

Depois disso, quando você fizer login, verá informações de rastreio que incluem o fornecimento de arquivos. No momento em que houver uma tentativa de declaração da função readonly existente, você verá uma mensagem de erro. O último arquivo originado antes dele deve conter a declaração que você procura.

Você pode precisar colocar isso no perfil bash do sistema. Lembre-se também de reverter as alterações depois de encontrar o culpado.

    
por 13.11.2016 / 05:30
-3

Você tentou isso?

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

ou qualquer outro comando encontrado aqui:

Como faço para encontrar todos os arquivos contendo texto específico no Linux? | Estouro de pilha

Parece que preciso dar mais uma explicação. Sua pergunta pergunta "" Portanto, se você executar o seguinte comando, ele deverá retornar todos os arquivos nos quais uma função bash está definida.

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

Programação BASH - Funções | Projeto de documentação do Linux

    
por 13.11.2016 / 04:46

Tags