This would probably never be the BEST approach to something, but I'm wondering if it's even possible.

Something like:

awk '/function_i_want_to_call/,/^$/{print}' script_containing_function | xargs source

function_i_want_to_call arg1 arg2 arg3

Except actually working.

  • The difference between source or . (dot) and just executing a script is whether it is done in your original shell process or in a new (subshell) process. For permanently setting variables or other shell properties (like cd) you need the first, which the answers address. If you only need to execute the commands you can pipe to a new shell like awk '/select/,/lines/' script | sh. Nov 14, 2015 at 2:14
  • Right, I'm aware of that. Though it just occurred to me that if the variables needed to be set are in the parent shell, they could be passed through with "export" and then just calling the other script normally. But it was the "only part of the other script" that was the focus of my question.
    – Wildcard
    Nov 14, 2015 at 3:59

3 Answers 3


First you need to rigorously determine what command will produce the specific part you want to source. For a trivial example, given the file


you could set only var1 using head -n1 filename. This could be a pipeline of arbitrary complexity, if you wanted.

Then run:

source <( pipeline_of_arbitrary_complexity some_filename )

Works only in bash. To do it in POSIX, I think you'd need to make a temp file.

  • I didn't realize <( command ) was bash-specific. But that's definitely the simplest answer, thanks.
    – Wildcard
    Jan 13, 2016 at 4:12

In bash/ksh and similar, you can use <() to avoid the subshell that | creates:


echo hallo welt
echo hello world
echo ahoj světe

Suppose you only want to in-source line number two:

. <( sed -n '2 p' < insourcable.sh )

(prints "hello world")

  • @mikeserv was alluding to what the OP was trying to do in the question, namely source in from the right-hand side of a pipeline. Obviously, it wouldn't work with xargs but it could work with something like echo echo foo | . /dev/stdin but that wouldn't be very useful because what's on the right hand side of a this pipeline is a subshell that cannot affect the parent shell. Nov 13, 2015 at 20:22
dotfn(){ . /dev/fd/0
} <<IN
        $(printf '\n%s(){ "$@" '"'\n" "$2"
          sed   -e"/$2.*{/,\$!d;s/^/    /"\
                -e"/^. *} *$/q;s/'/'"'\\&&/g'  <"$1"
          printf "\n';}")

obviously it's not fool proof, but it scans a file named in its first argument for the first series of input that begins with its second arg followed at some point on the same line with a { and pulls in all following lines until it encounters one which only matches blank space and a single }.

while sed does so it escapes all hard-quotes in input, and printf wraps the input in two hard-quotes and also prepends it with the string "$@". it sticks all of this in a function named for your second argument. here's an example:

printf '
        echo some stuff
        cat </dev/null

        for f in file*; do printf '\''%s\n'\'' "$f"; done
' >fn_file

i put those two functions in fn_file, and then...

dotfn fn_file another_fn

...nothing happened. but...

another_fn printf %s\\n

    for f in file*; do printf '%s\n' "$f"; done

i enclosed the function within one named for itself, and i can inspect it with printf or whatever, or i can redefine it:

another_fn eval; another_fn


I replaced the . /dev/fd/0 in dotfn() with a simple cat and went after some_fn():

dotfn fn_file some_fn

some_fn(){ "$@" '
        echo some stuff
        cat </dev/null


You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .