Comment définir une fonction Bash qui peut être utilisée par différents scripts


13

J'ai défini une bashfonction dans mon ~/.bashrcdossier. Cela me permet de l'utiliser dans des terminaux shell. Cependant, il ne semble pas exister lorsque je l'appelle depuis un script.

Comment puis-je définir une bashfonction à utiliser également par les scripts?


Mais mon .bash_profile lit fondamentalement le fichier .basrc, donc je m'attendrais à ce que le résultat soit le même, que j'utilise un shell de connexion ou non.
Onturenio

Utilisez-vous /bin/shdans la ligne shebang?
Kevin

Réponses:


9

~/.bash_profileet ~/.bashrcne sont pas lus par les scripts, et les fonctions ne sont pas exportées par défaut. Pour ce faire, vous pouvez utiliser export -fcomme suit:

$ 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 foopourrait également être appelé ~/.bash_profilepour rendre cette fonction disponible aux scripts après la connexion. Soyez averti que ce export -fn'est pas portable.

Une meilleure solution serait de trouver le fichier contenant la fonction en utilisant . file. C'est beaucoup plus portable et ne dépend pas de la configuration particulière de votre environnement.


pourquoi ne pas simplement déclarer une fonction comme function myFunction { ... }dans ~/.bash_profileet vous êtes prêt à partir?
amphibient

Si j'ai bien compris votre réponse (en ce qui concerne la recherche d'un fichier avec la fonction), cela signifierait que je dois source le fichier explicitement dans chaque script, ce qui est assez ennuyeux. Ce n'est pas beaucoup moins compliqué que de simplement copier-coller la fonction elle-même dans chaque script. Je voudrais enregistrer quelques lignes, bien sûr, mais c'est tout. Cependant, la exportsolution semble fonctionner correctement. Merci.
Onturenio

@foampile, c'est précisément ce que j'ai fait et ne fonctionne pas lors de l'appel de la fonction à partir d'un script.
Onturenio

1
@Onturenio: la deuxième méthode @ chris-down proposée est en effet meilleure: 1) Quand quelqu'un lit le script, il est conscient qu'il a besoin de certaines foofonctions de certains file2) Vous pouvez mieux contrôler le contenu de cela fileque vous assurer que le shell appelant n'a pas changé fooavant d'invoquer votre script. Vous pouvez ajouter des contrôles de sécurité filepour vous assurer qu'il n'est pas altéré, par exemple. (pas facile, mais possible). (eh bien, vous pouvez également faire ces vérifications sur la fonction foo définie ... mais vous obtenez ma dérive ^^ Je pense que la méthode 2 est plus propre.) 3) filene contiendra que ce qui est nécessaire, pas plus.
Olivier Dulac

8

.bashrcn'est lu que par des shells interactifs. (En fait, c'est une simplification excessive: bash est excentrique à cet égard. Bash ne lit pas.bashrc s'il s'agit d'un shell de connexion, interactif ou non. Et il y a une exception même à l'exception: si le processus parent de bash est rshdou sshd, alors bash lit .bashrc, que ce soit interactif ou non.)

Placez vos définitions de fonctions dans un fichier à un endroit connu et utilisez le .source module intégré (également orthographié ) pour inclure ce fichier dans un script.

$ cat ~/lib/bash/my_functions.bash
foo () {

$ cat ~/bin/myscript
#!/bin/bash
. ~/lib/bash/my_functions.bash
foo bar

Si vous le souhaitez, vous pouvez suivre la fonction de chargement automatique de ksh. Placez chaque définition de fonction dans un fichier portant le même nom que la fonction. Liste les répertoires contenant les définitions de fonction dans la FPATHvariable (une liste de répertoires séparés par deux-points). Voici une approximation grossière de ksh autoloadqui charge en fait la fonction immédiatement au lieu de sur demande:

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

+1 pour le chargement automatique, bien que je recommande d'utiliser ceux fournis avec bash. Le dernier prend en charge le chargement paresseux.
Starfish

0

Avez-vous besoin d' une fonction? Sinon, envisagez d'extraire la logique dans un script Bash distinct et autonome dans votre $PATH. Par exemple, j'avais ceci dans mon ~/.bashrc:

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

~/binest dans mon $PATH, j'ai donc créé ~/bin/wanipavec le contenu suivant:

#!/bin/bash

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

Et a couru chmod 0755 ~/bin/wanip pour le rendre exécutable. Maintenant, je peux exécuter à wanippartir d'autres scripts.

J'aime avoir wanipun script Bash autonome. Cela me rappelle que je veux que cette logique soit généralement disponible (en plus de ma session Bash interactive actuelle). Le script encapsule bien la logique et la documentation de celui-ci.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.