4

In Ubuntu 16.04 I have a Bash file containing a few different functions for automating various common tasks on my system.

I have sourced that file in bashrc so I could comfortably call each function from anywhere in the terminal in time of need, hence we can say that "the functions themselves are sourced".

Sometimes I need to use one of these sourced functions from inside a script, and I need to prim this action with:

export -f myFunc_0 myFunc_1 myFunc_2 ...

otherwise, I won't be able to use these functions.


How could I do that priming to all functions in the file, without noting specific functions?

  • 1
    I know you already know that this is a bad approach, but I'm noting it here explicitly for any future readers. – Michael Homer Mar 5 '18 at 5:20
6

If you use set -a either in your .bashrc or within the function file itself it will mark all functions to be exported.

4.3.1 The Set Builtin

-a

Each variable or function that is created or modified is given the export attribute and marked for export to the environment of subsequent commands.

This may cause some undesirable results if you are setting variables that you don't want exported, but you could add something like this to your .bashrc:

set -a
source ~/my_funcs
set +a
  • ok, but wouldn't calling set +a override the sourcing script if the sourcing script wanted it to be set -a, seems like not a good solution – Alexander Mills Aug 31 '18 at 20:58
  • @AlexanderMills: No, after you source the script all the functions will already be exported, calling set +a wont unset them it will just prevent future things from being exported – Jesse_b Aug 31 '18 at 22:37
  • depends from which context you call set +a, but it could affect shell if set -a was actually desired. Basically what I am saying is only call set +a if that was already set. – Alexander Mills Aug 31 '18 at 22:53
  • @AlexanderMills Did you even read my answer? I explicitly call set -a before sourcing the functions and then unset it immediately afterwards because it is almost never desired. – Jesse_b Sep 1 '18 at 10:20
8

What you should really do is source the file containing the functions inside the script itself, that way it won’t be context-dependent (or rather, it will be less context-dependent).

  • 1
    I am sorry but I don't know what this means, can you provide a short example? thx – Alexander Mills Aug 31 '18 at 20:59
6

You could try something like:

declare -fx $(bash -c 'source /path/to/my-file &> /dev/null; compgen -A function')

Since you want to export only functions from the file, sourcing it in a new instance of bash and then using compgen -A function will list names of all the functions defined in that file (and previously exported functions too, but that shouldn't be a problem here). Then you can use the output of that with export -f or declare -fx to export those functions.

As you're sourcing the file in your bashrc, re-sourcing it probably won't be a problem.

2
+100

Take a look at BASH_ENV

INVOCATION
          When bash is started non-interactively, to  run  a  shell script,  for
          example, it looks for the variable BASH_ENV in the environment, expands
          its value if it appears there, and uses the expanded value as the  name
          of  a  file to read and execute.  Bash behaves as if the following com‐
          mand were executed:
          if [ -n "$BASH_ENV" ]; then . "$BASH_ENV"; fi
          but the value of the PATH variable is not used to search for the  file‐
          name.

  BASH_ENV
          If  this parameter is set when bash is executing a shell script,
          its value is interpreted as a filename  containing  commands  to
          initialize the shell, as in ~/.bashrc.  The value of BASH_ENV is
          subjected to  parameter  expansion,  command  substitution,  and
          arithmetic  expansion  before  being  interpreted as a filename.
          PATH is not used to search for the resultant filename.

When bash execute a shell script non-interactively .bashrc is not read and the function file are not sourced.
If BASH_ENV is set to the name of the function file, this file is read and executed like said in INVOCATION.
So no need to source the function file in each shell script which use the function.

Example to illustrate :

Not Ubuntu but debian-linux 4.14.0-3-amd64 #1 SMP Debian 4.14.17-1 (2018-02-14) x86_64 GNU/Linux with Xfce 4.12

Create a file of functions in your $HOME

cat mesfuncbash

piste ()
{
echo $0 >> ~/lapiste
date >> ~/lapiste
}

Create a script which use the function

cat lescript

#!/bin/bash
echo $0
. ~/mesfuncbash
piste
echo fin

here the script source the function file

Create a laucher to lescript on the Desktop

No need of terminal

execute it.

The file ~/lapiste is updated.

Now remove . ~/mesfuncbash from lescript

execute it

The file ~/lapiste is not updated.

If you run lescript on a terminal

Bash tell you :

line 3: piste: command not found

Now you must set BASH_ENV to the name of the function file.

In debian with xfce, .profile is not read at startup so you can't use it to set BASH_ENV.

You must create a file .xsessionrc in your $HOME.

cat .xsessionrc

export BASH_ENV="$HOME/mesfuncbash"

logout and login, this way .xsessionrc is read at startup

Now, you can execute the laucher on the Desktop and the file ~/lapiste is updated.

  • Hi ctac_. I think you should add more markup to your question. Please consider that. – user9303970 Mar 21 '18 at 10:49
  • @user9303970 sorry, I don't understand 'add more markup to your question'. Do you want I add more explain ? – ctac_ Mar 21 '18 at 12:58
  • Sorry, I meant markdown, not markup. That is to ask, please add more formatting. There are some places you wrote code or paths and these are best to be formatted with the text-editor, in my opinion. – user9303970 Mar 21 '18 at 15:02
0

The output of set appears to be sorted favorably for extracting all defined functions. It starts with variables and then shows functions, soes:

set |awk '/^[^=()]*\(\)/ {functions=1} functions' > functions.sh

This looks for the first non-assignment (an occurrence of () before the first =) and then says that's okay to print. The second awk stanza uses the default print action when the variable functions is true. The output is saved in functions.sh, which can then be sourced elsewhere.

-2

Just use the env command:

env > /path/to/file
  • how is this supposed to work? explanation? – Alexander Mills Aug 31 '18 at 20:59

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.