0

I source a bashscript (Child) inside another bashscript (Parent), somewhere in the middle of Parent. The argument passed to Parent when executing it gets passed to the Child. How can I prevent this behavior? I don't want the arguments of parent to be transferred to Child as well.

NOTE: Parent Child analogy is not about Parent Child process, but about something that comes before the other.

Also, I wanted to have the environment of the Parent Script (except the arguments those are passed to it) for the sourced script. This is because, the default values for argument to the scripts are different. See Example Below. The parent script uses some of the functions defined in the sourced script and also the sourced script creates arrays that is being used by the parent script. Also, I need the positional parameters of the parent script, after the Child script is sourced.

#!/usr/bin/env bash
# - goal: "Parent"

main() {
    # # Path
    #dScriptP="$(dirname "$(readlink -f "${BASH_SOURCE[0]}")")"

    # # Argument
    ParentArgument=${1:-40}
    echo "ParentArgument=${ParentArgument}"
    . Child.sh

}

main "$@"
#!/bin/false
# shellcheck shell=bash
# - goal: "Child"

main() {
    # # Path
    #dScriptP="$(dirname "$(readlink -f "${BASH_SOURCE[0]}")")"

    # # Argument
    ChildArgument=${1:-30}
    echo "ChildArgument=${ChildArgument}"
}

main "$@"
$ ./Parent.sh 50
ParentArgument=50
ChildArgument=50

Desired Output

$ ./Parent.sh 50
ParentArgument=50
ChildArgument=30
3
  • Technically, you do not create a child when sourcing a script. It's like #include in C - you stay in the same process. Sep 15, 2019 at 17:40
  • And please post your scripts and explain what you want to achieve. Sep 15, 2019 at 17:42
  • We can't help you unless you give us a small example we can run to test the behavior you describe. Please edit your question and include such an example.
    – terdon
    Sep 15, 2019 at 18:26

2 Answers 2

3

You can POSIXly shift positional parameters with the shift [n] command (thanks @ilkkachu) where n is the number of parameters to shift (default is 1). To unset all parameters, you could shift all parameters with

shift $#

before you source your script.

The POSIXly way to change (set or unset) positional parameters is to use the set command. To unset all positional parameters, you could use

set --

before you source the script.

1
  • shift, and shift $# should be POSIX too.
    – ilkkachu
    Sep 15, 2019 at 18:15
2

POSIX description of the . "utility" (Bash's source is a synonym) goes:

NAME: dot - execute commands in the current environment
SYNOPSIS: . file
DESCRIPTION: The shell shall execute commands from the file in the current environment.

And the execution environment is defined to include:

Shell parameters that are set by variable assignment (see the set special built-in) or from [the environment]

That "set by variable assignment" doesn't really seem to match how the positional parameters (arguments) are initially assigned at shell startup, but the reference to set seems to imply that they should be included. And in any case, all shells I could find include them.

So, changing shells isn't likely to work, but you have some options:

  • Just unset the arguments, with set --. But then they wouldn't be available in the main shell after that either. In Bash/ksh/zsh, you could save them in an array first, args=("$@"), but of course that array would be visible to the sourced script.

  • Run the ./source in a function, since functions have their own set of arguments. Something like source() { . "$1"; } and then source script.sh, though that would make the name of sourced file visible in $1. Though that can be worked around, in Bash you could use source() { local f=$1; shift; . "$f"; };.

  • In Bash/ksh/zsh, you could add your own arguments to ./source, in which case only they would be available to the sourced script. After . script.sh foo the sourced script would only see foo in $1. But you can't pass an empty list of arguments that way.

  • Then again, if you don't want the other script to see the environment of the main script, then don't source it, but run it as a command instead, passing any required data explicitly through the scripts arguments, stdin and stdout.

You must log in to answer this question.

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