¿Puedo llamar a una función de un script de shell desde otro script de shell?

86

Tengo 2 scripts de shell.

El segundo script de shell contiene las siguientes funciones second.sh

func1 
func2

El first.sh llamará al segundo script de shell con algunos parámetros y llamará a func1 y func2 con algunos otros parámetros específicos de esa función.

Aquí está el ejemplo de lo que estoy hablando.

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

¿Cómo puedo lograrlo?

avirup
fuente
3
v=$(echo $1)es completamente redundante. Solo escribe fun2=$1. La única diferencia es que $()(o las comillas inversas) eliminarán las nuevas líneas finales.
William Pursell
1
Dado que no hay nada especial en llamar a una función desde un script de shell en lugar de la línea de comandos, esta pregunta se puede reducir a "¿Cómo llamar a una función bash?"
Tom Russell

Respuestas:

145

Refactorice su second.shscript de esta manera:

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}"
}

Y luego llame a estas funciones desde un script first.shcomo este:

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

SALIDA:

fun=love,book=horror
fun2=ball,book2=mystery
anubhava
fuente
12
Para evitar efectos secundarios involuntarios, tenga en cuenta que el sourcecomando ejecutará el script pasado como argumento.
dvlcube
43

No puede llamar directamente a una función en otro script de shell.

Puede mover las definiciones de sus funciones a un archivo separado y luego cargarlas en su script usando el .comando, así:

. /path/to/functions.sh

Esto se interpretará functions.shcomo si su contenido estuviera realmente presente en su archivo en este momento. Este es un mecanismo común para implementar bibliotecas compartidas de funciones de shell.

larsks
fuente
3
¿No es lo mismo que la respuesta aceptada, ya que .es un alias para source?
ajsharma
9
Bueno, respondí primero, así que técnicamente la respuesta aceptada es la misma que esta :). Además, aunque sourcees un alias de .en muchos shells, no siempre es así. Por ejemplo, el dashpaquete en Debian, que proporciona /bin/sh, no tiene un sourcecomando.
larsks
sourceEl comando no funcionó en Ubuntu @ajsharma. Referencia: comando fuente no encontrado en sh shell
rajeshmag
¿Tan extraño que este comentario no sea votado como el más alto? Esta es la sintaxis correcta #! / Bin / sh y la otra funcionará solo en bash.
xddq
20

El problema

La respuesta actualmente aceptada solo funciona en condiciones importantes. Dado...

/foo/bar/first.sh:

function func1 {  
   echo "Hello $1"
}

y

/foo/bar/second.sh:

#!/bin/bash

source ./first.sh
func1 World

esto solo funciona si first.shse ejecuta desde el mismo directorio donde first.shse encuentra. Es decir. si la ruta de trabajo actual del shell es /foo, el intento de ejecutar el comando

cd /foo
./bar/second.sh

imprime error:

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

Eso es porque source ./first.shes relativo a la ruta de trabajo actual, no a la ruta del script. Por lo tanto, una solución podría ser utilizar subshell y ejecutar

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

Solución más genérica

Dado...

/foo/bar/first.sh:

function func1 {  
   echo "Hello $1"
}

y

/foo/bar/second.sh:

#!/bin/bash

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

func1 World

entonces

cd /foo
./bar/second.sh

huellas dactilares

Hello World

Cómo funciona

  • $0 devuelve la ruta relativa o absoluta al script ejecutado
  • dirname devuelve la ruta relativa al directorio, donde existe el script $ 0
  • $( dirname "$0" )el dirname "$0"comando devuelve la ruta relativa al directorio del script ejecutado, que luego se usa como argumento para el sourcecomando
  • en "second.sh", /first.sh simplemente agrega el nombre del script de shell importado
  • source carga el contenido del archivo especificado en el shell actual
Patrik Stas
fuente
0

Si tu defines

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

en archivo1 (chmod 750 archivo1) y archivo2

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

y ejecute ./file2 obtendrá Fun1 de file1 Hello Fun1 de file2 Hello Surprise !!! Sobrescribe fun1 en file1 con fun1 de file2 ... Para no hacerlo, debe

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

es guardar su definición anterior para fun1 y restaurarla con el nombre anterior eliminando uno importado no necesario. Cada vez que importa funciones de otro archivo, puede recordar dos aspectos:

  1. puede sobrescribir los existentes con los mismos nombres (si eso es lo que desea, debe conservarlos como se describe anteriormente)
  2. importar todo el contenido del archivo de importación (funciones y variables globales también) ¡Tenga cuidado! Es un procedimiento peligroso
Anatoly
fuente
-5
#vi function.sh

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

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

#sh function.sh

Aquí la función f2llamará a la funciónf1

V.SANTOSH
fuente