Como definir uma função Bash que pode ser usada por diferentes scripts

12

Eu defini uma função bash no meu arquivo ~/.bashrc . Isso me permite usá-lo nos terminais do shell. No entanto, não parece existir quando eu chamo de dentro de um script.

Como posso definir uma função bash para ser usada também por scripts?

    
por Onturenio 04.02.2013 / 17:01

3 respostas

8

~/.bash_profile e ~/.bashrc não são lidos por scripts e as funções não são exportadas por padrão. Para fazer isso, você pode usar export -f da seguinte forma:

$ cat > script << 'EOF'
#!/bin/bash
foo
EOF
$ chmod a+x script
$ ./script
./script: line 2: foo: command not found
$ foo() { echo "works" ; } 
$ export -f foo
$ ./script
works

export -f foo também pode ser chamado em ~/.bash_profile para disponibilizar essa função a scripts após o login. Esteja avisado que export -f não é portátil.

Uma solução melhor seria fornecer o arquivo contendo a função usando . file . Isso é muito mais portátil e não depende do seu ambiente ser configurado de uma maneira particular.

    
por 04.02.2013 / 17:26
8

.bashrc é lido apenas por shells interativos. (Na verdade, isso é uma simplificação excessiva: o bash é peculiar a esse respeito. O Bash não lê .bashrc se for um shell de login, interativo ou não. E há uma exceção até mesmo à exceção: se o processo pai do bash for rshd ou sshd , então o bash lê .bashrc , seja ele interativo ou não.

Coloque suas definições de função em um arquivo em um local conhecido e use o . (também escrito source ) incorporado para incluir esse arquivo em um script.

$ cat ~/lib/bash/my_functions.bash
foo () {
…
$ cat ~/bin/myscript
#!/bin/bash
. ~/lib/bash/my_functions.bash
foo bar

Se você quiser, você pode seguir o recurso de carregamento automático do ksh. Coloque cada definição de função em um arquivo com o mesmo nome da função. Listar os diretórios que contêm as definições de função na variável FPATH (uma lista de diretórios separados por dois-pontos). Aqui está uma aproximação grosseira de autoload de ksh que realmente carrega a função imediatamente em vez de sob demanda:

autoload () {
  set -- "$(set +f; IFS=:;
            for d in $FPATH; do
              if [ -r "$d/$1" ]; then echo -E "$d/$1"; break; fi;
            done)"
  [[ -n $1 ]] && . "$1"
}
    
por 05.02.2013 / 02:10
0

Você precisa de uma função? Se não, considere retirar a lógica em um script Bash autônomo separado em seu $PATH . Por exemplo, eu tive isso no meu ~/.bashrc :

# echo public IP address
alias wanip='dig +short myip.opendns.com @resolver1.opendns.com'

~/bin está no meu $PATH , então criei ~/bin/wanip com o seguinte conteúdo:

#!/bin/bash

# echo public IP address
dig +short myip.opendns.com @resolver1.opendns.com

E executei chmod 0755 ~/bin/wanip para torná-lo executável. Agora posso executar wanip de outros scripts.

Eu gosto de ter wanip em um script autônomo de Bash. Isso me lembra que eu quero essa lógica geralmente disponível (além de apenas na minha sessão Bash interativa atual). O script encapsula bem a lógica e a documentação para o mesmo.

    
por 13.02.2015 / 00:55