Posso chamar uma função de um script de shell de outro script de shell?

86

Eu tenho 2 scripts de shell.

O segundo script de shell contém as seguintes funções second.sh

func1 
func2

O first.sh chamará o segundo script de shell com alguns parâmetros e chamará func1 e func2 com alguns outros parâmetros específicos dessa função.

Aqui está o exemplo do que estou falando

second.sh

val1=`echo $1`
val2=`echo $2`

function func1 {

fun=`echo $1`
book=`echo $2`

}

function func2 {

fun2=`echo $1`
book2=`echo $2`


}

first.sh

second.sh cricket football

func1 love horror
func2 ball mystery

Como posso conseguir isso?

avirup
fonte
3
v=$(echo $1)é completamente redundante. Basta escrever fun2=$1. A única diferença é que os $()(ou crases) removerão as novas linhas finais.
William Pursell
1
Como não há nada de especial em chamar uma função de um script de shell em oposição à linha de comando, esta questão pode ser reduzida a "Como chamar uma função bash?"
Tom Russell,

Respostas:

145

Refatore seu second.shscript assim:

function func1 {
   fun=$1
   book=$2
   printf "fun=%s,book=%s\n" "${fun}" "${book}"
}

function func2 {
   fun2=$1
   book2=$2
   printf "fun2=%s,book2=%s\n" "${fun2}" "${book2}"
}

Em seguida, chame essas funções do script first.shcomo este:

source ./second.sh
func1 love horror
func2 ball mystery

RESULTADO:

fun=love,book=horror
fun2=ball,book2=mystery
anubhava
fonte
12
Para evitar efeitos colaterais não intencionais, tome cuidado para que o sourcecomando realmente execute o script passado como argumento.
dvlcube
43

Você não pode chamar diretamente uma função em outro script de shell.

Você pode mover suas definições de função para um arquivo separado e, em seguida, carregá-las em seu script usando o .comando, como este:

. /path/to/functions.sh

Isso interpretará functions.shcomo se o conteúdo estivesse realmente presente em seu arquivo neste momento. Este é um mecanismo comum para implementar bibliotecas compartilhadas de funções de shell.

larsks
fonte
3
Não é a mesma que a resposta aceita, já que .é um alias para source?
ajsharma de
9
Bem, eu respondi primeiro, então tecnicamente a resposta aceita é a mesma que esta :). Além disso, embora sourceseja um apelido para .em muitos shells, esse nem sempre é o caso. Por exemplo, o dashpacote no Debian, que fornece /bin/sh, não tem um sourcecomando.
larsks de
sourcecomando não funcionou no Ubuntu @ajsharma. Referência: comando de origem não encontrado no sh shell
rajeshmag
tão estranho que este comentário não foi votado como o mais alto? Esta é a sintaxe #! / Bin / sh correta e a outra funcionará apenas no bash.
xddq
20

O problema

A resposta atualmente aceita funciona apenas em condições importantes. Dado...

/foo/bar/first.sh:

function func1 {  
   echo "Hello $1"
}

e

/foo/bar/second.sh:

#!/bin/bash

source ./first.sh
func1 World

isso funciona apenas se o first.shfor executado no mesmo diretório em que first.shestá localizado. Ie. se o caminho de trabalho atual do shell for /foo, a tentativa de executar o comando

cd /foo
./bar/second.sh

imprime erro:

/foo/bar/second.sh: line 4: func1: command not found

Isso porque source ./first.shé relativo ao caminho de trabalho atual, não ao caminho do script. Portanto, uma solução pode ser utilizar subshell e executar

(cd /foo/bar; ./second.sh)

Solução mais genérica

Dado...

/foo/bar/first.sh:

function func1 {  
   echo "Hello $1"
}

e

/foo/bar/second.sh:

#!/bin/bash

source $(dirname "$0")/first.sh

func1 World

então

cd /foo
./bar/second.sh

estampas

Hello World

Como funciona

  • $0 retorna o caminho relativo ou absoluto para o script executado
  • dirname retorna o caminho relativo para o diretório, onde existe o script $ 0
  • $( dirname "$0" )o dirname "$0"comando retorna o caminho relativo para o diretório do script executado, que é então usado como argumento para o sourcecomando
  • em "second.sh", /first.shapenas acrescenta o nome do script de shell importado
  • source carrega o conteúdo do arquivo especificado no shell atual
Patrik Stas
fonte
0

Se você definir

    #!/bin/bash
        fun1(){
          echo "Fun1 from file1 $1"
        }
fun1 Hello
. file2 
fun1 Hello
exit 0

em arquivo1 (chmod 750 arquivo1) e arquivo2

   fun1(){
      echo "Fun1 from file2 $1"
    }
    fun2(){
      echo "Fun1 from file1 $1"
    }

e execute ./file2 você obterá Fun1 de file1 Hello Fun1 de file2 Hello Surprise !!! Você sobrescreve fun1 no arquivo1 com fun1 do arquivo2 ... Para não fazer isso, você deve

declare -f pr_fun1=$fun1
. file2
unset -f fun1
fun1=$pr_fun1
unset -f pr_fun1
fun1 Hello

é salvar sua definição anterior para se divertir1 e restaurá-la com o nome anterior, excluindo não é necessário importar um. Cada vez que você importa funções de outro arquivo, você pode se lembrar de dois aspectos:

  1. você pode sobrescrever os existentes com os mesmos nomes (se for essa a coisa que você deseja, você deve preservá-los conforme descrito acima)
  2. importe todo o conteúdo do arquivo de importação (funções e variáveis ​​globais também). Cuidado! É procedimento perigoso
Anatoly
fonte
-5
#vi function.sh

#!/bin/bash
f1() {
    echo "Hello $name"
}

f2() {
    echo "Enter your name: "
    read name
    f1
}
f2

#sh function.sh

Aqui, a função f2irá chamar a funçãof1

V.SANTOSH
fonte