Respostas:
Ative a depuração. A partir do manual Bash :
extdebug
Se definido na chamada do shell ou em um arquivo de inicialização do shell, organize a execução do perfil do depurador antes do início do shell, idêntico à
--debugger
opção. Se definido após a invocação, o comportamento destinado ao uso por depuradores será ativado:
- A
-F
opção para o built-indeclare
(consulte Bash Builtins ) exibe o nome do arquivo de origem e o número da linha correspondente a cada nome de função fornecido como argumento.
Exemplo:
$ bash --debugger
$ declare -Ff quote
quote 143 /usr/share/bash-completion/bash_completion
E realmente:
$ nl -ba /usr/share/bash-completion/bash_completion | sed -n 143,150p
143 quote()
144 {
145 local quoted=${1//\'/\'\\\'\'}
146 printf "'%s'" "$quoted"
147 }
148
149 # @see _quote_readline_by_ref()
150 quote_readline()
shopt -s extdebug; declare -Ff quote; shopt -u extdebug
.
find_function()( shopt -s extdebug; declare -F "$@"; )
. Com os parênteses no corpo da função, ele é executado em um subshell e a alteração para shopts não afeta o chamador. E o -f
não parece ser necessário.
Isso é realmente mais complicado do que parece à primeira vista. Quais arquivos são lidos pelo seu shell depende do tipo de shell que você está executando no momento. Seja interativo ou não, seja um shell de logon ou não-logon e qual combinação dos itens acima. Para pesquisar em todos os arquivos padrão que podem ser lidos pelos diferentes shells, você pode fazer (mude $functionName
para o nome real da função que está procurando):
grep "$functionName" ~/.bashrc ~/.profile ~/.bash_profile ~/.bash.login \
~/.bash_aliases /etc/bash.bashrc /etc/profile \
/etc/profile.d/* /etc/environment 2> /dev/null
Se isso não funcionar, você pode estar chamando um arquivo não padrão usando .
ou seu alias source
. Para encontrar esses casos, execute:
grep -P '(^|\s)(\.|source)\s+' ~/.bashrc ~/.profile ~/.bash_profile \
~/.bash.login ~/.bash_aliases /etc/bash.bashrc \
/etc/profile /etc/profile.d/* /etc/environment 2> /dev/null
Isso provavelmente precisa de alguma explicação. Ele -P
habilita PCRE (Perl Compatible Regular Expressions), que nos permite usar alguma sintaxe de regex mais sofisticada. Especificamente:
(^|\s)
: corresponde ao início de uma linha ( ^
) ou espaço em branco ( \s
).(\.|source)\s+
: corresponde a um .
caractere literal ( \.
) ou à palavra source
, mas somente se forem seguidos por um ou mais caracteres de espaço em branco.Aqui está o que isso me dá no meu sistema:
$ grep -P '(^|\s)(\.|source)\s+' ~/.bashrc ~/.profile ~/.bash_profile \
> ~/.bash.login ~/.bash_aliases /etc/bash.bashrc \
> /etc/profile /etc/profile.d/* /etc/environment 2> /dev/null
/home/terdon/.bashrc: . /etc/bashrc
/home/terdon/.bashrc: . /etc/bash_completion
/home/terdon/.bashrc:. $HOME/scripts/git-prompt.sh
/home/terdon/.bashrc:# echo -n "$n : "; grep "^CA" $n |perl -e 'my ($a,$c)=0; while(<>){$c++;next if /cellular_component_unknown/; next if /biological_process/; $a++} print "$a Classes of $c annotated (" . $a*100/$c . ")\n"'
/etc/bash.bashrc:[ -r /usr/share/bash-completion/bash_completion ] && . /usr/share/bash-completion/bash_completion
/etc/profile: test -r "$profile" && . "$profile"
/etc/profile: . /etc/bash.bashrc
/etc/profile.d/locale.sh: . "$XDG_CONFIG_HOME/locale.conf"
/etc/profile.d/locale.sh: . "$HOME/.config/locale.conf"
/etc/profile.d/locale.sh: . /etc/locale.conf
/etc/profile.d/Z97-byobu.sh: . /usr/bin/byobu-launch
/etc/profile.d/Z97-byobu.sh: . /usr/bin/byobu-launch
/etc/profile.d/Z97-byobu.sh: . /usr/bin/byobu-launch
/etc/profile.d/Z97-byobu.sh: . /usr/bin/byobu-launch
/etc/profile.d/Z97-byobu.sh: . /usr/bin/byobu-launch
Como você pode ver, no entanto, isso imprimirá toda a linha correspondente. O que realmente interessa é a lista de nomes de arquivos chamados, não a linha que os chama. Você pode obter aqueles com este regex mais complicado:
grep -hPo '(^|\s)(\.|source)\s+\K\S+' ~/.bashrc ~/.profile ~/.bash_profile \
~/.bash.login ~/.bash_aliases \
/etc/bash.bashrc /etc/profile \
/etc/profile.d/* /etc/environment 2> /dev/null
O -h
sinalizador suprime a impressão dos nomes dos arquivos onde uma correspondência foi encontrada, o que grep
ocorre por padrão quando solicitado a pesquisar em vários arquivos. Os -o
meios "apenas imprimem a parte correspondente da linha". O material extra adicionado ao regex é:
\K
: ignore qualquer coisa que corresponda a esse ponto. Esse é um truque do PCRE que permite usar um regex complexo para encontrar sua correspondência, mas não incluir a parte correspondente ao usar o -o
sinalizador grep .No meu sistema, o comando acima retornará:
$ grep -hPo '(^|\s)(\.|source)\s+\K\S+' ~/.bashrc ~/.profile ~/.bash_profile \
> ~/.bash.login ~/.bash_aliases \
> /etc/bash.bashrc /etc/profile \
> /etc/profile.d/* /etc/environment 2> /dev/null
/etc/bashrc
/etc/bash_completion
$HOME/scripts/git-prompt.sh
$a*100/$c
")\n"'
/usr/share/bash-completion/bash_completion
"$profile"
/etc/bash.bashrc
"$XDG_CONFIG_HOME/locale.conf"
"$HOME/.config/locale.conf"
/etc/locale.conf
/usr/bin/byobu-launch
/usr/bin/byobu-launch
/usr/bin/byobu-launch
/usr/bin/byobu-launch
/usr/bin/byobu-launch
Observe que, por acaso, uso um .
seguido de um espaço que não é usado para fornecimento, mas é porque eu tenho um alias que está chamando outro idioma, não o bash. Isso é o que dá o estranho $a*100/$c
e ")\n"'
na saída acima. Mas isso pode ser ignorado.
Por fim, veja como reunir tudo isso e procurar um nome de função em todos os arquivos padrão e em todos os arquivos que seus arquivos padrão estão procurando:
grep_function(){
target="$@"
files=( ~/.bashrc ~/.profile ~/.bash_profile ~/.bash.login
~/.bash_aliases /etc/bash.bashrc /etc/profile
/etc/profile.d/* /etc/environment)
while IFS= read -r file; do
files+=( "$file" )
done < <(grep -hPo '(^|\s)(\.|source)\s+\K\S+' "${files[@]}" 2>/dev/null)
for file in "${files[@]}"; do
## The tilde of ~/ can break this
file=$(sed 's|~/|'"$HOME"'/|g' <<<"$file")
if [[ -e $file ]]; then
grep -H "$target" -- "$file"
fi
done
}
Adicione essas linhas ao seu ~/.bashrc
e você poderá executar (estou usando fooBar
como exemplo o nome da função):
grep_function fooBar
Por exemplo, se eu tiver essa linha no meu ~/.bashrc
:
. ~/a
E o arquivo ~/a
é:
$ cat ~/a
fooBar(){
echo foo
}
Eu deveria encontrá-lo com:
$ grep_function fooBar
/home/terdon/a:fooBar(){
+=
array+="foo"
anexar a string foo
ao 1º elemento da matriz?
O habitual por usuário dotfile bash
lê é ~/.bashrc
. No entanto, pode muito bem fonte outros arquivos, por exemplo, eu gosto de manter aliases e funções em arquivos separados chamados ~/.bash_aliases
e ~/.bash_functions
, o que torna muito mais fácil encontrá-los. Você pode pesquisar o .bashrc
para source
comandos com:
grep -E '(^\s*|\s)(\.|source)\s' /home/USERNAME/.bashrc
Depois de ter a lista de arquivos criados pelo usuário, você pode procurá-los e o usuário .bashrc
com uma única grep
chamada, por exemplo, a função foo
para minha configuração:
grep foo /home/USERNAME/.bash{rc,_aliases,_functions}