Parameters passed to a sourced script are wrong
Clash Royale CLAN TAG#URR8PPP
up vote
2
down vote
favorite
A script on AIX which checks the number of parameters passed and complains if they are not correct:-
if [ "$#" -ge 1 ]; then
...
else
echo 'Usage: myscript <a> [b] [c]'
fi
The script sets some environment variables so it is sourced. By that I mean I type the following on my command line. There is no second script, I am not sourcing a script from within another script.
. ./myscript.sh
If I pass it no parameters, I expect it to print out the usage statement but instead it runs using the parameters passed to the previous command that was sourced (not necessarily even this script!).
To double check this I added this line at the beginning of my script to prove that this was the case.
echo $# $@
If I pass it no parameters, it prints out the number and the list of parameters from a previously sourced script.
How do I get it to say $#
is zero when I pass it zero parameters and source it?
The smallest possible recreate is a script thus:-
myscript.sh
echo $# $@
and then run it thus:-
. ./myscript.sh a b c
which prints out
3 a b c
then run it again without any parameters thus:-
. ./myscript.sh
which prints out the same
3 a b c
when you would expect it to print out
0
If you don't source the script and just run it thus:-
./myscript.sh
then it works as expected and prints out
0
I hope that clarifies the issue at hand.
Since I seem to be getting lots of answers to explain why the above doesn't work and no answers to tell me what I should do instead, I thought I would have one more attempt at trying to explain what I am trying to do.
Requirement
I need to write a script that expects at least one parameter and complains if it is not invoked with a said parameter (see the first block of code in my question above), and this script needs to set some environment variables. Because of this second requirement I have assumed that I need to source the script so that the environment variables are still set when the script completes. How can you write a script that can tell when it has not been passed parameters that is also able to set an environment variable?
shell-script aix parameter source-command
add a comment |Â
up vote
2
down vote
favorite
A script on AIX which checks the number of parameters passed and complains if they are not correct:-
if [ "$#" -ge 1 ]; then
...
else
echo 'Usage: myscript <a> [b] [c]'
fi
The script sets some environment variables so it is sourced. By that I mean I type the following on my command line. There is no second script, I am not sourcing a script from within another script.
. ./myscript.sh
If I pass it no parameters, I expect it to print out the usage statement but instead it runs using the parameters passed to the previous command that was sourced (not necessarily even this script!).
To double check this I added this line at the beginning of my script to prove that this was the case.
echo $# $@
If I pass it no parameters, it prints out the number and the list of parameters from a previously sourced script.
How do I get it to say $#
is zero when I pass it zero parameters and source it?
The smallest possible recreate is a script thus:-
myscript.sh
echo $# $@
and then run it thus:-
. ./myscript.sh a b c
which prints out
3 a b c
then run it again without any parameters thus:-
. ./myscript.sh
which prints out the same
3 a b c
when you would expect it to print out
0
If you don't source the script and just run it thus:-
./myscript.sh
then it works as expected and prints out
0
I hope that clarifies the issue at hand.
Since I seem to be getting lots of answers to explain why the above doesn't work and no answers to tell me what I should do instead, I thought I would have one more attempt at trying to explain what I am trying to do.
Requirement
I need to write a script that expects at least one parameter and complains if it is not invoked with a said parameter (see the first block of code in my question above), and this script needs to set some environment variables. Because of this second requirement I have assumed that I need to source the script so that the environment variables are still set when the script completes. How can you write a script that can tell when it has not been passed parameters that is also able to set an environment variable?
shell-script aix parameter source-command
Possible duplicate of Passing variables to a bash script when sourcing it
â Patrick
May 3 at 12:05
3
This should work. Which shell are you using? Post a small, complete pair of scripts (the sourcing script and the sourced script) that reproduces the problem.
â Gilles
May 3 at 12:25
@Patrick That's not a duplicate: it explains that what Morag is trying to do should work.
â Gilles
May 3 at 12:26
@Gilles - I don't understand what you mean by a "pair of scripts". There is only one script which I run from the command line with the command shown in my question. ./myscript.sh
. If I don't provide any parameters, e.g.. ./myscript.sh abc
then the script runs with parameters from a previously sourced command.
â Morag Hughson
May 3 at 21:32
I seem to be getting lots of explanations about why what I have done doesn't work, but no answers to tell me what I should do instead. Perhaps I didn't ask the question very well. I have edited my question to try and make it clearer what I am trying to do. Perhaps then someone can tell me how I should have coded my script.
â Morag Hughson
May 5 at 0:55
add a comment |Â
up vote
2
down vote
favorite
up vote
2
down vote
favorite
A script on AIX which checks the number of parameters passed and complains if they are not correct:-
if [ "$#" -ge 1 ]; then
...
else
echo 'Usage: myscript <a> [b] [c]'
fi
The script sets some environment variables so it is sourced. By that I mean I type the following on my command line. There is no second script, I am not sourcing a script from within another script.
. ./myscript.sh
If I pass it no parameters, I expect it to print out the usage statement but instead it runs using the parameters passed to the previous command that was sourced (not necessarily even this script!).
To double check this I added this line at the beginning of my script to prove that this was the case.
echo $# $@
If I pass it no parameters, it prints out the number and the list of parameters from a previously sourced script.
How do I get it to say $#
is zero when I pass it zero parameters and source it?
The smallest possible recreate is a script thus:-
myscript.sh
echo $# $@
and then run it thus:-
. ./myscript.sh a b c
which prints out
3 a b c
then run it again without any parameters thus:-
. ./myscript.sh
which prints out the same
3 a b c
when you would expect it to print out
0
If you don't source the script and just run it thus:-
./myscript.sh
then it works as expected and prints out
0
I hope that clarifies the issue at hand.
Since I seem to be getting lots of answers to explain why the above doesn't work and no answers to tell me what I should do instead, I thought I would have one more attempt at trying to explain what I am trying to do.
Requirement
I need to write a script that expects at least one parameter and complains if it is not invoked with a said parameter (see the first block of code in my question above), and this script needs to set some environment variables. Because of this second requirement I have assumed that I need to source the script so that the environment variables are still set when the script completes. How can you write a script that can tell when it has not been passed parameters that is also able to set an environment variable?
shell-script aix parameter source-command
A script on AIX which checks the number of parameters passed and complains if they are not correct:-
if [ "$#" -ge 1 ]; then
...
else
echo 'Usage: myscript <a> [b] [c]'
fi
The script sets some environment variables so it is sourced. By that I mean I type the following on my command line. There is no second script, I am not sourcing a script from within another script.
. ./myscript.sh
If I pass it no parameters, I expect it to print out the usage statement but instead it runs using the parameters passed to the previous command that was sourced (not necessarily even this script!).
To double check this I added this line at the beginning of my script to prove that this was the case.
echo $# $@
If I pass it no parameters, it prints out the number and the list of parameters from a previously sourced script.
How do I get it to say $#
is zero when I pass it zero parameters and source it?
The smallest possible recreate is a script thus:-
myscript.sh
echo $# $@
and then run it thus:-
. ./myscript.sh a b c
which prints out
3 a b c
then run it again without any parameters thus:-
. ./myscript.sh
which prints out the same
3 a b c
when you would expect it to print out
0
If you don't source the script and just run it thus:-
./myscript.sh
then it works as expected and prints out
0
I hope that clarifies the issue at hand.
Since I seem to be getting lots of answers to explain why the above doesn't work and no answers to tell me what I should do instead, I thought I would have one more attempt at trying to explain what I am trying to do.
Requirement
I need to write a script that expects at least one parameter and complains if it is not invoked with a said parameter (see the first block of code in my question above), and this script needs to set some environment variables. Because of this second requirement I have assumed that I need to source the script so that the environment variables are still set when the script completes. How can you write a script that can tell when it has not been passed parameters that is also able to set an environment variable?
shell-script aix parameter source-command
edited May 5 at 0:52
asked May 3 at 11:09
Morag Hughson
1144
1144
Possible duplicate of Passing variables to a bash script when sourcing it
â Patrick
May 3 at 12:05
3
This should work. Which shell are you using? Post a small, complete pair of scripts (the sourcing script and the sourced script) that reproduces the problem.
â Gilles
May 3 at 12:25
@Patrick That's not a duplicate: it explains that what Morag is trying to do should work.
â Gilles
May 3 at 12:26
@Gilles - I don't understand what you mean by a "pair of scripts". There is only one script which I run from the command line with the command shown in my question. ./myscript.sh
. If I don't provide any parameters, e.g.. ./myscript.sh abc
then the script runs with parameters from a previously sourced command.
â Morag Hughson
May 3 at 21:32
I seem to be getting lots of explanations about why what I have done doesn't work, but no answers to tell me what I should do instead. Perhaps I didn't ask the question very well. I have edited my question to try and make it clearer what I am trying to do. Perhaps then someone can tell me how I should have coded my script.
â Morag Hughson
May 5 at 0:55
add a comment |Â
Possible duplicate of Passing variables to a bash script when sourcing it
â Patrick
May 3 at 12:05
3
This should work. Which shell are you using? Post a small, complete pair of scripts (the sourcing script and the sourced script) that reproduces the problem.
â Gilles
May 3 at 12:25
@Patrick That's not a duplicate: it explains that what Morag is trying to do should work.
â Gilles
May 3 at 12:26
@Gilles - I don't understand what you mean by a "pair of scripts". There is only one script which I run from the command line with the command shown in my question. ./myscript.sh
. If I don't provide any parameters, e.g.. ./myscript.sh abc
then the script runs with parameters from a previously sourced command.
â Morag Hughson
May 3 at 21:32
I seem to be getting lots of explanations about why what I have done doesn't work, but no answers to tell me what I should do instead. Perhaps I didn't ask the question very well. I have edited my question to try and make it clearer what I am trying to do. Perhaps then someone can tell me how I should have coded my script.
â Morag Hughson
May 5 at 0:55
Possible duplicate of Passing variables to a bash script when sourcing it
â Patrick
May 3 at 12:05
Possible duplicate of Passing variables to a bash script when sourcing it
â Patrick
May 3 at 12:05
3
3
This should work. Which shell are you using? Post a small, complete pair of scripts (the sourcing script and the sourced script) that reproduces the problem.
â Gilles
May 3 at 12:25
This should work. Which shell are you using? Post a small, complete pair of scripts (the sourcing script and the sourced script) that reproduces the problem.
â Gilles
May 3 at 12:25
@Patrick That's not a duplicate: it explains that what Morag is trying to do should work.
â Gilles
May 3 at 12:26
@Patrick That's not a duplicate: it explains that what Morag is trying to do should work.
â Gilles
May 3 at 12:26
@Gilles - I don't understand what you mean by a "pair of scripts". There is only one script which I run from the command line with the command shown in my question
. ./myscript.sh
. If I don't provide any parameters, e.g. . ./myscript.sh abc
then the script runs with parameters from a previously sourced command.â Morag Hughson
May 3 at 21:32
@Gilles - I don't understand what you mean by a "pair of scripts". There is only one script which I run from the command line with the command shown in my question
. ./myscript.sh
. If I don't provide any parameters, e.g. . ./myscript.sh abc
then the script runs with parameters from a previously sourced command.â Morag Hughson
May 3 at 21:32
I seem to be getting lots of explanations about why what I have done doesn't work, but no answers to tell me what I should do instead. Perhaps I didn't ask the question very well. I have edited my question to try and make it clearer what I am trying to do. Perhaps then someone can tell me how I should have coded my script.
â Morag Hughson
May 5 at 0:55
I seem to be getting lots of explanations about why what I have done doesn't work, but no answers to tell me what I should do instead. Perhaps I didn't ask the question very well. I have edited my question to try and make it clearer what I am trying to do. Perhaps then someone can tell me how I should have coded my script.
â Morag Hughson
May 5 at 0:55
add a comment |Â
3 Answers
3
active
oldest
votes
up vote
2
down vote
In
. path/to/script at least one argument
As others have said, depending on the shell, those extra arguments are either ignored (Bourne, Almquist) or replace the current set of positional parameters ($@
, $1
, $2
...) for the interpretation of that script (most other shells). POSIX doesn't specify the behaviour when extra arguments are passed to .
. In that case, there is also some variation between shells as to whether any change to the positional parameters (like with set a b
) made within the script will remain after .
finishes.
In:
. path/to/script
however, the behaviour is specified. The positional parameters are required not to be affected, so will stay the same as before for the interpretation of the script.
If you want the positional parameters to be an empty list during the interpretation of that script, you'll need to reset it before hand, or use a function:
set -- # or shift "$#"
. path/to/script
(though the positional parameters are lost). Or use a function:
dot() file=$1; shift; . "$file";
dot path/to/myscript
At the time the .
command is executed, the positional parameters will be that of the function. After the shift
, it will be the arguments passed to the function minus the first one, so in the above, an empty list; but that means that with that function you can portably pass an arbitrary list of positional parameters to the sourced script as in:
dot path/to/myscript extra args
Where those extra
args
will be available as $1
and $2
within the sourced script.
And if myscript
calls set
to modify the list of positional parameters, that will only affect the function's positional parameters, and those changes will not persist after the function returns.
Thank you for your answer. I seem to be getting lots of explanations about why what I have done doesn't work, but no answers to tell me what I should do instead. Perhaps I didn't ask the question very well. I will edit my question to try and make it clearer what I am trying to do. Perhaps then someone can tell me how I should have coded my script.
â Morag Hughson
May 5 at 0:46
I've read and re-read your answer a few times now and I'm struggling to understand how to put it into practice. The reason I want to test whether the correct parameters were passed to the script is because I can't trust the user running it to do the correct thing. If they have to type another command prior to running it, I can't trust them to do that either. With the function - is this something inside my script that will somehow fix the way the parameters are given to the script?
â Morag Hughson
May 7 at 9:37
1
@MoragHughson, the gist of it is that you cannot pass arbitrary lists of arguments to a sourced script on the command line (. script arbitrary list
), so you need to document a different way to pass arguments to your script, for instance using that function trick, or using a dedicate variable instead of positional arguments.
â Stéphane Chazelas
May 7 at 9:41
What you just wrote should be an answer. That was the impression I have been getting from all these complicated explanations that I didn't understand how they solved my problem. But no-one was saying it explicitly. If you write that as an answer I will accept it. Or put that as the first sentence in this answer.
â Morag Hughson
May 7 at 9:47
add a comment |Â
up vote
2
down vote
Bash's help text for .
:
.: . filename [arguments]
Execute commands from a file in the current shell.
Read and execute commands from FILENAME in the current shell. The
entries in $PATH are used to find the directory containing FILENAME.
If any ARGUMENTS are supplied, they become the positional parameters
when FILENAME is executed.
Note the phrasing: "if any arguments are supplied". Without arguments, the current positional parameters stay.
$ cat /tmp/sourceme.sh
printf "%d: " "$#"
printf "<%s> " "$@"
printf "n"
$ bash -c 'set -- aa bb; . /tmp/sourceme.sh'
2: <aa> <bb>
$ bash -c 'set -- aa bb; . /tmp/sourceme.sh foo bar'
2: <foo> <bar>
All other shells I tested (zsh, ksh) behave similarly. Except for dash
, which always leaves the original positional parameters in place.
$ dash -c 'set -- aa bb; . /tmp/sourceme.sh foo bar'
2: <aa> <bb>
I can't see any mention about resetting the positional parameters in the POSIX definition of .
so it would seem that giving arguments to .
is nonstandard to begin with.
Instead of a sourced script, you could use a function, as they can accept arguments in a standard shell. In this case you'd source a file that defines the function.
E.g. a file (define_fun.sh
) with the function definition:
#!/bin/sh
f()
echo "args: $# $@" # just a test
if [ "$#" = 0 ]; then
echo please give at least one argument
return 1
fi;
ENVVAR=$1 # this should be visible to the whole shell
export ENVVAR # and any commands called later
And then use it:
$ . define_fun.sh # source the file to load the func in the current shell
$ f # actually run it: this'll complain
$ f 123 456 # this should set ENVVAR
$ echo $ENVVAR # and this will print '123'
You could instead put the function definition in one of the shell's initialization files (~/.profile
? Depends on the shell.)
Thank you for your answer - are you telling me that I need to use this-c 'set --
construct for it to work? I'm a little confused by whether your answer is a solution for me or an explanation of why it will never work? I have updated my original question with a few more examples to hopefully clear up any confusion about what I was asking.
â Morag Hughson
May 3 at 21:41
@MoragHughson, it's an explanation of why you don't get the result you expect: you're expecting behaviour that's not in the standard, and which your shell apparently doesn't implement. Theset -- a b
is there to set the positional parameters of the shell sourcing the script, just so that we can see what values come from the outside of the sourced script.
â ilkkachu
May 4 at 9:49
@MoragHughson, the additions you made to the question don't show what the positional parameters are before you used. myscript.sh
, so we can't tell what happens. I would expect that they containa
,b
,c
, before you called. myscript.sh
the first time, so that's what you get if your shell doesn't support giving arguments to.
.
â ilkkachu
May 4 at 9:52
I do apologise, I thought I had written that I ran the script like this:-. ./myscript a b c
and then I ran the script a second time like this:-. ./myscript
and on that second invocation I got the parameters from the first invocation of the script when I expected to get zero.
â Morag Hughson
May 5 at 0:35
Perhaps part of my problem is I don't understand where this-c set --
operator comes into the picture? I'm not using that anywhere. I don't know what it is for. I'm just passing parameters into my script by typing them after the script file name.
â Morag Hughson
May 5 at 0:40
 |Â
show 6 more comments
up vote
0
down vote
Passing arguments to the dot
builtin command is a Korn Shell extension that is not granted to work in other shells.
Since the POSIX standard does not mention $# and $@ for the dot command, the arguments to the current shell are visible to the dot command, so if you call your shell e.g. as:
myshell -s a b c
and then call
. ./myscript.sh
this is expected to print
3 a b c
1
I think they are not passing arguments todot
yet the dotted script is picking up the existing args (which OP didnâÂÂt expect)
â Jeff Schaller
May 3 at 17:46
When I pass parameters to my script, e.g.. ./myscript.sh a b c
it works fine. My question is about when I don't pass parameters.
â Morag Hughson
May 3 at 21:43
pubs.opengroup.org/onlinepubs/9699919799/utilities/⦠is the official standard for the command. From a POSIX view, $# is expected to be 0 in all cases (unless the shell implements an extension. In special, in your second example, $# is expected to be 0, except if you called your shell ac$shell -c 1a b c
.
â schily
May 4 at 10:06
I seem to be getting lots of explanations about why what I have done doesn't work, but no answers to tell me what I should do instead. Perhaps I didn't ask the question very well. I have edited my question to try and make it clearer what I am trying to do. Perhaps then someone can tell me how I should have coded my script.
â Morag Hughson
May 5 at 0:55
add a comment |Â
3 Answers
3
active
oldest
votes
3 Answers
3
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
2
down vote
In
. path/to/script at least one argument
As others have said, depending on the shell, those extra arguments are either ignored (Bourne, Almquist) or replace the current set of positional parameters ($@
, $1
, $2
...) for the interpretation of that script (most other shells). POSIX doesn't specify the behaviour when extra arguments are passed to .
. In that case, there is also some variation between shells as to whether any change to the positional parameters (like with set a b
) made within the script will remain after .
finishes.
In:
. path/to/script
however, the behaviour is specified. The positional parameters are required not to be affected, so will stay the same as before for the interpretation of the script.
If you want the positional parameters to be an empty list during the interpretation of that script, you'll need to reset it before hand, or use a function:
set -- # or shift "$#"
. path/to/script
(though the positional parameters are lost). Or use a function:
dot() file=$1; shift; . "$file";
dot path/to/myscript
At the time the .
command is executed, the positional parameters will be that of the function. After the shift
, it will be the arguments passed to the function minus the first one, so in the above, an empty list; but that means that with that function you can portably pass an arbitrary list of positional parameters to the sourced script as in:
dot path/to/myscript extra args
Where those extra
args
will be available as $1
and $2
within the sourced script.
And if myscript
calls set
to modify the list of positional parameters, that will only affect the function's positional parameters, and those changes will not persist after the function returns.
Thank you for your answer. I seem to be getting lots of explanations about why what I have done doesn't work, but no answers to tell me what I should do instead. Perhaps I didn't ask the question very well. I will edit my question to try and make it clearer what I am trying to do. Perhaps then someone can tell me how I should have coded my script.
â Morag Hughson
May 5 at 0:46
I've read and re-read your answer a few times now and I'm struggling to understand how to put it into practice. The reason I want to test whether the correct parameters were passed to the script is because I can't trust the user running it to do the correct thing. If they have to type another command prior to running it, I can't trust them to do that either. With the function - is this something inside my script that will somehow fix the way the parameters are given to the script?
â Morag Hughson
May 7 at 9:37
1
@MoragHughson, the gist of it is that you cannot pass arbitrary lists of arguments to a sourced script on the command line (. script arbitrary list
), so you need to document a different way to pass arguments to your script, for instance using that function trick, or using a dedicate variable instead of positional arguments.
â Stéphane Chazelas
May 7 at 9:41
What you just wrote should be an answer. That was the impression I have been getting from all these complicated explanations that I didn't understand how they solved my problem. But no-one was saying it explicitly. If you write that as an answer I will accept it. Or put that as the first sentence in this answer.
â Morag Hughson
May 7 at 9:47
add a comment |Â
up vote
2
down vote
In
. path/to/script at least one argument
As others have said, depending on the shell, those extra arguments are either ignored (Bourne, Almquist) or replace the current set of positional parameters ($@
, $1
, $2
...) for the interpretation of that script (most other shells). POSIX doesn't specify the behaviour when extra arguments are passed to .
. In that case, there is also some variation between shells as to whether any change to the positional parameters (like with set a b
) made within the script will remain after .
finishes.
In:
. path/to/script
however, the behaviour is specified. The positional parameters are required not to be affected, so will stay the same as before for the interpretation of the script.
If you want the positional parameters to be an empty list during the interpretation of that script, you'll need to reset it before hand, or use a function:
set -- # or shift "$#"
. path/to/script
(though the positional parameters are lost). Or use a function:
dot() file=$1; shift; . "$file";
dot path/to/myscript
At the time the .
command is executed, the positional parameters will be that of the function. After the shift
, it will be the arguments passed to the function minus the first one, so in the above, an empty list; but that means that with that function you can portably pass an arbitrary list of positional parameters to the sourced script as in:
dot path/to/myscript extra args
Where those extra
args
will be available as $1
and $2
within the sourced script.
And if myscript
calls set
to modify the list of positional parameters, that will only affect the function's positional parameters, and those changes will not persist after the function returns.
Thank you for your answer. I seem to be getting lots of explanations about why what I have done doesn't work, but no answers to tell me what I should do instead. Perhaps I didn't ask the question very well. I will edit my question to try and make it clearer what I am trying to do. Perhaps then someone can tell me how I should have coded my script.
â Morag Hughson
May 5 at 0:46
I've read and re-read your answer a few times now and I'm struggling to understand how to put it into practice. The reason I want to test whether the correct parameters were passed to the script is because I can't trust the user running it to do the correct thing. If they have to type another command prior to running it, I can't trust them to do that either. With the function - is this something inside my script that will somehow fix the way the parameters are given to the script?
â Morag Hughson
May 7 at 9:37
1
@MoragHughson, the gist of it is that you cannot pass arbitrary lists of arguments to a sourced script on the command line (. script arbitrary list
), so you need to document a different way to pass arguments to your script, for instance using that function trick, or using a dedicate variable instead of positional arguments.
â Stéphane Chazelas
May 7 at 9:41
What you just wrote should be an answer. That was the impression I have been getting from all these complicated explanations that I didn't understand how they solved my problem. But no-one was saying it explicitly. If you write that as an answer I will accept it. Or put that as the first sentence in this answer.
â Morag Hughson
May 7 at 9:47
add a comment |Â
up vote
2
down vote
up vote
2
down vote
In
. path/to/script at least one argument
As others have said, depending on the shell, those extra arguments are either ignored (Bourne, Almquist) or replace the current set of positional parameters ($@
, $1
, $2
...) for the interpretation of that script (most other shells). POSIX doesn't specify the behaviour when extra arguments are passed to .
. In that case, there is also some variation between shells as to whether any change to the positional parameters (like with set a b
) made within the script will remain after .
finishes.
In:
. path/to/script
however, the behaviour is specified. The positional parameters are required not to be affected, so will stay the same as before for the interpretation of the script.
If you want the positional parameters to be an empty list during the interpretation of that script, you'll need to reset it before hand, or use a function:
set -- # or shift "$#"
. path/to/script
(though the positional parameters are lost). Or use a function:
dot() file=$1; shift; . "$file";
dot path/to/myscript
At the time the .
command is executed, the positional parameters will be that of the function. After the shift
, it will be the arguments passed to the function minus the first one, so in the above, an empty list; but that means that with that function you can portably pass an arbitrary list of positional parameters to the sourced script as in:
dot path/to/myscript extra args
Where those extra
args
will be available as $1
and $2
within the sourced script.
And if myscript
calls set
to modify the list of positional parameters, that will only affect the function's positional parameters, and those changes will not persist after the function returns.
In
. path/to/script at least one argument
As others have said, depending on the shell, those extra arguments are either ignored (Bourne, Almquist) or replace the current set of positional parameters ($@
, $1
, $2
...) for the interpretation of that script (most other shells). POSIX doesn't specify the behaviour when extra arguments are passed to .
. In that case, there is also some variation between shells as to whether any change to the positional parameters (like with set a b
) made within the script will remain after .
finishes.
In:
. path/to/script
however, the behaviour is specified. The positional parameters are required not to be affected, so will stay the same as before for the interpretation of the script.
If you want the positional parameters to be an empty list during the interpretation of that script, you'll need to reset it before hand, or use a function:
set -- # or shift "$#"
. path/to/script
(though the positional parameters are lost). Or use a function:
dot() file=$1; shift; . "$file";
dot path/to/myscript
At the time the .
command is executed, the positional parameters will be that of the function. After the shift
, it will be the arguments passed to the function minus the first one, so in the above, an empty list; but that means that with that function you can portably pass an arbitrary list of positional parameters to the sourced script as in:
dot path/to/myscript extra args
Where those extra
args
will be available as $1
and $2
within the sourced script.
And if myscript
calls set
to modify the list of positional parameters, that will only affect the function's positional parameters, and those changes will not persist after the function returns.
edited May 5 at 5:43
answered May 4 at 10:47
Stéphane Chazelas
279k53514846
279k53514846
Thank you for your answer. I seem to be getting lots of explanations about why what I have done doesn't work, but no answers to tell me what I should do instead. Perhaps I didn't ask the question very well. I will edit my question to try and make it clearer what I am trying to do. Perhaps then someone can tell me how I should have coded my script.
â Morag Hughson
May 5 at 0:46
I've read and re-read your answer a few times now and I'm struggling to understand how to put it into practice. The reason I want to test whether the correct parameters were passed to the script is because I can't trust the user running it to do the correct thing. If they have to type another command prior to running it, I can't trust them to do that either. With the function - is this something inside my script that will somehow fix the way the parameters are given to the script?
â Morag Hughson
May 7 at 9:37
1
@MoragHughson, the gist of it is that you cannot pass arbitrary lists of arguments to a sourced script on the command line (. script arbitrary list
), so you need to document a different way to pass arguments to your script, for instance using that function trick, or using a dedicate variable instead of positional arguments.
â Stéphane Chazelas
May 7 at 9:41
What you just wrote should be an answer. That was the impression I have been getting from all these complicated explanations that I didn't understand how they solved my problem. But no-one was saying it explicitly. If you write that as an answer I will accept it. Or put that as the first sentence in this answer.
â Morag Hughson
May 7 at 9:47
add a comment |Â
Thank you for your answer. I seem to be getting lots of explanations about why what I have done doesn't work, but no answers to tell me what I should do instead. Perhaps I didn't ask the question very well. I will edit my question to try and make it clearer what I am trying to do. Perhaps then someone can tell me how I should have coded my script.
â Morag Hughson
May 5 at 0:46
I've read and re-read your answer a few times now and I'm struggling to understand how to put it into practice. The reason I want to test whether the correct parameters were passed to the script is because I can't trust the user running it to do the correct thing. If they have to type another command prior to running it, I can't trust them to do that either. With the function - is this something inside my script that will somehow fix the way the parameters are given to the script?
â Morag Hughson
May 7 at 9:37
1
@MoragHughson, the gist of it is that you cannot pass arbitrary lists of arguments to a sourced script on the command line (. script arbitrary list
), so you need to document a different way to pass arguments to your script, for instance using that function trick, or using a dedicate variable instead of positional arguments.
â Stéphane Chazelas
May 7 at 9:41
What you just wrote should be an answer. That was the impression I have been getting from all these complicated explanations that I didn't understand how they solved my problem. But no-one was saying it explicitly. If you write that as an answer I will accept it. Or put that as the first sentence in this answer.
â Morag Hughson
May 7 at 9:47
Thank you for your answer. I seem to be getting lots of explanations about why what I have done doesn't work, but no answers to tell me what I should do instead. Perhaps I didn't ask the question very well. I will edit my question to try and make it clearer what I am trying to do. Perhaps then someone can tell me how I should have coded my script.
â Morag Hughson
May 5 at 0:46
Thank you for your answer. I seem to be getting lots of explanations about why what I have done doesn't work, but no answers to tell me what I should do instead. Perhaps I didn't ask the question very well. I will edit my question to try and make it clearer what I am trying to do. Perhaps then someone can tell me how I should have coded my script.
â Morag Hughson
May 5 at 0:46
I've read and re-read your answer a few times now and I'm struggling to understand how to put it into practice. The reason I want to test whether the correct parameters were passed to the script is because I can't trust the user running it to do the correct thing. If they have to type another command prior to running it, I can't trust them to do that either. With the function - is this something inside my script that will somehow fix the way the parameters are given to the script?
â Morag Hughson
May 7 at 9:37
I've read and re-read your answer a few times now and I'm struggling to understand how to put it into practice. The reason I want to test whether the correct parameters were passed to the script is because I can't trust the user running it to do the correct thing. If they have to type another command prior to running it, I can't trust them to do that either. With the function - is this something inside my script that will somehow fix the way the parameters are given to the script?
â Morag Hughson
May 7 at 9:37
1
1
@MoragHughson, the gist of it is that you cannot pass arbitrary lists of arguments to a sourced script on the command line (
. script arbitrary list
), so you need to document a different way to pass arguments to your script, for instance using that function trick, or using a dedicate variable instead of positional arguments.â Stéphane Chazelas
May 7 at 9:41
@MoragHughson, the gist of it is that you cannot pass arbitrary lists of arguments to a sourced script on the command line (
. script arbitrary list
), so you need to document a different way to pass arguments to your script, for instance using that function trick, or using a dedicate variable instead of positional arguments.â Stéphane Chazelas
May 7 at 9:41
What you just wrote should be an answer. That was the impression I have been getting from all these complicated explanations that I didn't understand how they solved my problem. But no-one was saying it explicitly. If you write that as an answer I will accept it. Or put that as the first sentence in this answer.
â Morag Hughson
May 7 at 9:47
What you just wrote should be an answer. That was the impression I have been getting from all these complicated explanations that I didn't understand how they solved my problem. But no-one was saying it explicitly. If you write that as an answer I will accept it. Or put that as the first sentence in this answer.
â Morag Hughson
May 7 at 9:47
add a comment |Â
up vote
2
down vote
Bash's help text for .
:
.: . filename [arguments]
Execute commands from a file in the current shell.
Read and execute commands from FILENAME in the current shell. The
entries in $PATH are used to find the directory containing FILENAME.
If any ARGUMENTS are supplied, they become the positional parameters
when FILENAME is executed.
Note the phrasing: "if any arguments are supplied". Without arguments, the current positional parameters stay.
$ cat /tmp/sourceme.sh
printf "%d: " "$#"
printf "<%s> " "$@"
printf "n"
$ bash -c 'set -- aa bb; . /tmp/sourceme.sh'
2: <aa> <bb>
$ bash -c 'set -- aa bb; . /tmp/sourceme.sh foo bar'
2: <foo> <bar>
All other shells I tested (zsh, ksh) behave similarly. Except for dash
, which always leaves the original positional parameters in place.
$ dash -c 'set -- aa bb; . /tmp/sourceme.sh foo bar'
2: <aa> <bb>
I can't see any mention about resetting the positional parameters in the POSIX definition of .
so it would seem that giving arguments to .
is nonstandard to begin with.
Instead of a sourced script, you could use a function, as they can accept arguments in a standard shell. In this case you'd source a file that defines the function.
E.g. a file (define_fun.sh
) with the function definition:
#!/bin/sh
f()
echo "args: $# $@" # just a test
if [ "$#" = 0 ]; then
echo please give at least one argument
return 1
fi;
ENVVAR=$1 # this should be visible to the whole shell
export ENVVAR # and any commands called later
And then use it:
$ . define_fun.sh # source the file to load the func in the current shell
$ f # actually run it: this'll complain
$ f 123 456 # this should set ENVVAR
$ echo $ENVVAR # and this will print '123'
You could instead put the function definition in one of the shell's initialization files (~/.profile
? Depends on the shell.)
Thank you for your answer - are you telling me that I need to use this-c 'set --
construct for it to work? I'm a little confused by whether your answer is a solution for me or an explanation of why it will never work? I have updated my original question with a few more examples to hopefully clear up any confusion about what I was asking.
â Morag Hughson
May 3 at 21:41
@MoragHughson, it's an explanation of why you don't get the result you expect: you're expecting behaviour that's not in the standard, and which your shell apparently doesn't implement. Theset -- a b
is there to set the positional parameters of the shell sourcing the script, just so that we can see what values come from the outside of the sourced script.
â ilkkachu
May 4 at 9:49
@MoragHughson, the additions you made to the question don't show what the positional parameters are before you used. myscript.sh
, so we can't tell what happens. I would expect that they containa
,b
,c
, before you called. myscript.sh
the first time, so that's what you get if your shell doesn't support giving arguments to.
.
â ilkkachu
May 4 at 9:52
I do apologise, I thought I had written that I ran the script like this:-. ./myscript a b c
and then I ran the script a second time like this:-. ./myscript
and on that second invocation I got the parameters from the first invocation of the script when I expected to get zero.
â Morag Hughson
May 5 at 0:35
Perhaps part of my problem is I don't understand where this-c set --
operator comes into the picture? I'm not using that anywhere. I don't know what it is for. I'm just passing parameters into my script by typing them after the script file name.
â Morag Hughson
May 5 at 0:40
 |Â
show 6 more comments
up vote
2
down vote
Bash's help text for .
:
.: . filename [arguments]
Execute commands from a file in the current shell.
Read and execute commands from FILENAME in the current shell. The
entries in $PATH are used to find the directory containing FILENAME.
If any ARGUMENTS are supplied, they become the positional parameters
when FILENAME is executed.
Note the phrasing: "if any arguments are supplied". Without arguments, the current positional parameters stay.
$ cat /tmp/sourceme.sh
printf "%d: " "$#"
printf "<%s> " "$@"
printf "n"
$ bash -c 'set -- aa bb; . /tmp/sourceme.sh'
2: <aa> <bb>
$ bash -c 'set -- aa bb; . /tmp/sourceme.sh foo bar'
2: <foo> <bar>
All other shells I tested (zsh, ksh) behave similarly. Except for dash
, which always leaves the original positional parameters in place.
$ dash -c 'set -- aa bb; . /tmp/sourceme.sh foo bar'
2: <aa> <bb>
I can't see any mention about resetting the positional parameters in the POSIX definition of .
so it would seem that giving arguments to .
is nonstandard to begin with.
Instead of a sourced script, you could use a function, as they can accept arguments in a standard shell. In this case you'd source a file that defines the function.
E.g. a file (define_fun.sh
) with the function definition:
#!/bin/sh
f()
echo "args: $# $@" # just a test
if [ "$#" = 0 ]; then
echo please give at least one argument
return 1
fi;
ENVVAR=$1 # this should be visible to the whole shell
export ENVVAR # and any commands called later
And then use it:
$ . define_fun.sh # source the file to load the func in the current shell
$ f # actually run it: this'll complain
$ f 123 456 # this should set ENVVAR
$ echo $ENVVAR # and this will print '123'
You could instead put the function definition in one of the shell's initialization files (~/.profile
? Depends on the shell.)
Thank you for your answer - are you telling me that I need to use this-c 'set --
construct for it to work? I'm a little confused by whether your answer is a solution for me or an explanation of why it will never work? I have updated my original question with a few more examples to hopefully clear up any confusion about what I was asking.
â Morag Hughson
May 3 at 21:41
@MoragHughson, it's an explanation of why you don't get the result you expect: you're expecting behaviour that's not in the standard, and which your shell apparently doesn't implement. Theset -- a b
is there to set the positional parameters of the shell sourcing the script, just so that we can see what values come from the outside of the sourced script.
â ilkkachu
May 4 at 9:49
@MoragHughson, the additions you made to the question don't show what the positional parameters are before you used. myscript.sh
, so we can't tell what happens. I would expect that they containa
,b
,c
, before you called. myscript.sh
the first time, so that's what you get if your shell doesn't support giving arguments to.
.
â ilkkachu
May 4 at 9:52
I do apologise, I thought I had written that I ran the script like this:-. ./myscript a b c
and then I ran the script a second time like this:-. ./myscript
and on that second invocation I got the parameters from the first invocation of the script when I expected to get zero.
â Morag Hughson
May 5 at 0:35
Perhaps part of my problem is I don't understand where this-c set --
operator comes into the picture? I'm not using that anywhere. I don't know what it is for. I'm just passing parameters into my script by typing them after the script file name.
â Morag Hughson
May 5 at 0:40
 |Â
show 6 more comments
up vote
2
down vote
up vote
2
down vote
Bash's help text for .
:
.: . filename [arguments]
Execute commands from a file in the current shell.
Read and execute commands from FILENAME in the current shell. The
entries in $PATH are used to find the directory containing FILENAME.
If any ARGUMENTS are supplied, they become the positional parameters
when FILENAME is executed.
Note the phrasing: "if any arguments are supplied". Without arguments, the current positional parameters stay.
$ cat /tmp/sourceme.sh
printf "%d: " "$#"
printf "<%s> " "$@"
printf "n"
$ bash -c 'set -- aa bb; . /tmp/sourceme.sh'
2: <aa> <bb>
$ bash -c 'set -- aa bb; . /tmp/sourceme.sh foo bar'
2: <foo> <bar>
All other shells I tested (zsh, ksh) behave similarly. Except for dash
, which always leaves the original positional parameters in place.
$ dash -c 'set -- aa bb; . /tmp/sourceme.sh foo bar'
2: <aa> <bb>
I can't see any mention about resetting the positional parameters in the POSIX definition of .
so it would seem that giving arguments to .
is nonstandard to begin with.
Instead of a sourced script, you could use a function, as they can accept arguments in a standard shell. In this case you'd source a file that defines the function.
E.g. a file (define_fun.sh
) with the function definition:
#!/bin/sh
f()
echo "args: $# $@" # just a test
if [ "$#" = 0 ]; then
echo please give at least one argument
return 1
fi;
ENVVAR=$1 # this should be visible to the whole shell
export ENVVAR # and any commands called later
And then use it:
$ . define_fun.sh # source the file to load the func in the current shell
$ f # actually run it: this'll complain
$ f 123 456 # this should set ENVVAR
$ echo $ENVVAR # and this will print '123'
You could instead put the function definition in one of the shell's initialization files (~/.profile
? Depends on the shell.)
Bash's help text for .
:
.: . filename [arguments]
Execute commands from a file in the current shell.
Read and execute commands from FILENAME in the current shell. The
entries in $PATH are used to find the directory containing FILENAME.
If any ARGUMENTS are supplied, they become the positional parameters
when FILENAME is executed.
Note the phrasing: "if any arguments are supplied". Without arguments, the current positional parameters stay.
$ cat /tmp/sourceme.sh
printf "%d: " "$#"
printf "<%s> " "$@"
printf "n"
$ bash -c 'set -- aa bb; . /tmp/sourceme.sh'
2: <aa> <bb>
$ bash -c 'set -- aa bb; . /tmp/sourceme.sh foo bar'
2: <foo> <bar>
All other shells I tested (zsh, ksh) behave similarly. Except for dash
, which always leaves the original positional parameters in place.
$ dash -c 'set -- aa bb; . /tmp/sourceme.sh foo bar'
2: <aa> <bb>
I can't see any mention about resetting the positional parameters in the POSIX definition of .
so it would seem that giving arguments to .
is nonstandard to begin with.
Instead of a sourced script, you could use a function, as they can accept arguments in a standard shell. In this case you'd source a file that defines the function.
E.g. a file (define_fun.sh
) with the function definition:
#!/bin/sh
f()
echo "args: $# $@" # just a test
if [ "$#" = 0 ]; then
echo please give at least one argument
return 1
fi;
ENVVAR=$1 # this should be visible to the whole shell
export ENVVAR # and any commands called later
And then use it:
$ . define_fun.sh # source the file to load the func in the current shell
$ f # actually run it: this'll complain
$ f 123 456 # this should set ENVVAR
$ echo $ENVVAR # and this will print '123'
You could instead put the function definition in one of the shell's initialization files (~/.profile
? Depends on the shell.)
edited May 7 at 7:51
answered May 3 at 12:34
ilkkachu
48.2k669133
48.2k669133
Thank you for your answer - are you telling me that I need to use this-c 'set --
construct for it to work? I'm a little confused by whether your answer is a solution for me or an explanation of why it will never work? I have updated my original question with a few more examples to hopefully clear up any confusion about what I was asking.
â Morag Hughson
May 3 at 21:41
@MoragHughson, it's an explanation of why you don't get the result you expect: you're expecting behaviour that's not in the standard, and which your shell apparently doesn't implement. Theset -- a b
is there to set the positional parameters of the shell sourcing the script, just so that we can see what values come from the outside of the sourced script.
â ilkkachu
May 4 at 9:49
@MoragHughson, the additions you made to the question don't show what the positional parameters are before you used. myscript.sh
, so we can't tell what happens. I would expect that they containa
,b
,c
, before you called. myscript.sh
the first time, so that's what you get if your shell doesn't support giving arguments to.
.
â ilkkachu
May 4 at 9:52
I do apologise, I thought I had written that I ran the script like this:-. ./myscript a b c
and then I ran the script a second time like this:-. ./myscript
and on that second invocation I got the parameters from the first invocation of the script when I expected to get zero.
â Morag Hughson
May 5 at 0:35
Perhaps part of my problem is I don't understand where this-c set --
operator comes into the picture? I'm not using that anywhere. I don't know what it is for. I'm just passing parameters into my script by typing them after the script file name.
â Morag Hughson
May 5 at 0:40
 |Â
show 6 more comments
Thank you for your answer - are you telling me that I need to use this-c 'set --
construct for it to work? I'm a little confused by whether your answer is a solution for me or an explanation of why it will never work? I have updated my original question with a few more examples to hopefully clear up any confusion about what I was asking.
â Morag Hughson
May 3 at 21:41
@MoragHughson, it's an explanation of why you don't get the result you expect: you're expecting behaviour that's not in the standard, and which your shell apparently doesn't implement. Theset -- a b
is there to set the positional parameters of the shell sourcing the script, just so that we can see what values come from the outside of the sourced script.
â ilkkachu
May 4 at 9:49
@MoragHughson, the additions you made to the question don't show what the positional parameters are before you used. myscript.sh
, so we can't tell what happens. I would expect that they containa
,b
,c
, before you called. myscript.sh
the first time, so that's what you get if your shell doesn't support giving arguments to.
.
â ilkkachu
May 4 at 9:52
I do apologise, I thought I had written that I ran the script like this:-. ./myscript a b c
and then I ran the script a second time like this:-. ./myscript
and on that second invocation I got the parameters from the first invocation of the script when I expected to get zero.
â Morag Hughson
May 5 at 0:35
Perhaps part of my problem is I don't understand where this-c set --
operator comes into the picture? I'm not using that anywhere. I don't know what it is for. I'm just passing parameters into my script by typing them after the script file name.
â Morag Hughson
May 5 at 0:40
Thank you for your answer - are you telling me that I need to use this
-c 'set --
construct for it to work? I'm a little confused by whether your answer is a solution for me or an explanation of why it will never work? I have updated my original question with a few more examples to hopefully clear up any confusion about what I was asking.â Morag Hughson
May 3 at 21:41
Thank you for your answer - are you telling me that I need to use this
-c 'set --
construct for it to work? I'm a little confused by whether your answer is a solution for me or an explanation of why it will never work? I have updated my original question with a few more examples to hopefully clear up any confusion about what I was asking.â Morag Hughson
May 3 at 21:41
@MoragHughson, it's an explanation of why you don't get the result you expect: you're expecting behaviour that's not in the standard, and which your shell apparently doesn't implement. The
set -- a b
is there to set the positional parameters of the shell sourcing the script, just so that we can see what values come from the outside of the sourced script.â ilkkachu
May 4 at 9:49
@MoragHughson, it's an explanation of why you don't get the result you expect: you're expecting behaviour that's not in the standard, and which your shell apparently doesn't implement. The
set -- a b
is there to set the positional parameters of the shell sourcing the script, just so that we can see what values come from the outside of the sourced script.â ilkkachu
May 4 at 9:49
@MoragHughson, the additions you made to the question don't show what the positional parameters are before you used
. myscript.sh
, so we can't tell what happens. I would expect that they contain a
, b
, c
, before you called . myscript.sh
the first time, so that's what you get if your shell doesn't support giving arguments to .
.â ilkkachu
May 4 at 9:52
@MoragHughson, the additions you made to the question don't show what the positional parameters are before you used
. myscript.sh
, so we can't tell what happens. I would expect that they contain a
, b
, c
, before you called . myscript.sh
the first time, so that's what you get if your shell doesn't support giving arguments to .
.â ilkkachu
May 4 at 9:52
I do apologise, I thought I had written that I ran the script like this:-
. ./myscript a b c
and then I ran the script a second time like this:- . ./myscript
and on that second invocation I got the parameters from the first invocation of the script when I expected to get zero.â Morag Hughson
May 5 at 0:35
I do apologise, I thought I had written that I ran the script like this:-
. ./myscript a b c
and then I ran the script a second time like this:- . ./myscript
and on that second invocation I got the parameters from the first invocation of the script when I expected to get zero.â Morag Hughson
May 5 at 0:35
Perhaps part of my problem is I don't understand where this
-c set --
operator comes into the picture? I'm not using that anywhere. I don't know what it is for. I'm just passing parameters into my script by typing them after the script file name.â Morag Hughson
May 5 at 0:40
Perhaps part of my problem is I don't understand where this
-c set --
operator comes into the picture? I'm not using that anywhere. I don't know what it is for. I'm just passing parameters into my script by typing them after the script file name.â Morag Hughson
May 5 at 0:40
 |Â
show 6 more comments
up vote
0
down vote
Passing arguments to the dot
builtin command is a Korn Shell extension that is not granted to work in other shells.
Since the POSIX standard does not mention $# and $@ for the dot command, the arguments to the current shell are visible to the dot command, so if you call your shell e.g. as:
myshell -s a b c
and then call
. ./myscript.sh
this is expected to print
3 a b c
1
I think they are not passing arguments todot
yet the dotted script is picking up the existing args (which OP didnâÂÂt expect)
â Jeff Schaller
May 3 at 17:46
When I pass parameters to my script, e.g.. ./myscript.sh a b c
it works fine. My question is about when I don't pass parameters.
â Morag Hughson
May 3 at 21:43
pubs.opengroup.org/onlinepubs/9699919799/utilities/⦠is the official standard for the command. From a POSIX view, $# is expected to be 0 in all cases (unless the shell implements an extension. In special, in your second example, $# is expected to be 0, except if you called your shell ac$shell -c 1a b c
.
â schily
May 4 at 10:06
I seem to be getting lots of explanations about why what I have done doesn't work, but no answers to tell me what I should do instead. Perhaps I didn't ask the question very well. I have edited my question to try and make it clearer what I am trying to do. Perhaps then someone can tell me how I should have coded my script.
â Morag Hughson
May 5 at 0:55
add a comment |Â
up vote
0
down vote
Passing arguments to the dot
builtin command is a Korn Shell extension that is not granted to work in other shells.
Since the POSIX standard does not mention $# and $@ for the dot command, the arguments to the current shell are visible to the dot command, so if you call your shell e.g. as:
myshell -s a b c
and then call
. ./myscript.sh
this is expected to print
3 a b c
1
I think they are not passing arguments todot
yet the dotted script is picking up the existing args (which OP didnâÂÂt expect)
â Jeff Schaller
May 3 at 17:46
When I pass parameters to my script, e.g.. ./myscript.sh a b c
it works fine. My question is about when I don't pass parameters.
â Morag Hughson
May 3 at 21:43
pubs.opengroup.org/onlinepubs/9699919799/utilities/⦠is the official standard for the command. From a POSIX view, $# is expected to be 0 in all cases (unless the shell implements an extension. In special, in your second example, $# is expected to be 0, except if you called your shell ac$shell -c 1a b c
.
â schily
May 4 at 10:06
I seem to be getting lots of explanations about why what I have done doesn't work, but no answers to tell me what I should do instead. Perhaps I didn't ask the question very well. I have edited my question to try and make it clearer what I am trying to do. Perhaps then someone can tell me how I should have coded my script.
â Morag Hughson
May 5 at 0:55
add a comment |Â
up vote
0
down vote
up vote
0
down vote
Passing arguments to the dot
builtin command is a Korn Shell extension that is not granted to work in other shells.
Since the POSIX standard does not mention $# and $@ for the dot command, the arguments to the current shell are visible to the dot command, so if you call your shell e.g. as:
myshell -s a b c
and then call
. ./myscript.sh
this is expected to print
3 a b c
Passing arguments to the dot
builtin command is a Korn Shell extension that is not granted to work in other shells.
Since the POSIX standard does not mention $# and $@ for the dot command, the arguments to the current shell are visible to the dot command, so if you call your shell e.g. as:
myshell -s a b c
and then call
. ./myscript.sh
this is expected to print
3 a b c
edited May 4 at 10:10
answered May 3 at 14:23
schily
8,67031435
8,67031435
1
I think they are not passing arguments todot
yet the dotted script is picking up the existing args (which OP didnâÂÂt expect)
â Jeff Schaller
May 3 at 17:46
When I pass parameters to my script, e.g.. ./myscript.sh a b c
it works fine. My question is about when I don't pass parameters.
â Morag Hughson
May 3 at 21:43
pubs.opengroup.org/onlinepubs/9699919799/utilities/⦠is the official standard for the command. From a POSIX view, $# is expected to be 0 in all cases (unless the shell implements an extension. In special, in your second example, $# is expected to be 0, except if you called your shell ac$shell -c 1a b c
.
â schily
May 4 at 10:06
I seem to be getting lots of explanations about why what I have done doesn't work, but no answers to tell me what I should do instead. Perhaps I didn't ask the question very well. I have edited my question to try and make it clearer what I am trying to do. Perhaps then someone can tell me how I should have coded my script.
â Morag Hughson
May 5 at 0:55
add a comment |Â
1
I think they are not passing arguments todot
yet the dotted script is picking up the existing args (which OP didnâÂÂt expect)
â Jeff Schaller
May 3 at 17:46
When I pass parameters to my script, e.g.. ./myscript.sh a b c
it works fine. My question is about when I don't pass parameters.
â Morag Hughson
May 3 at 21:43
pubs.opengroup.org/onlinepubs/9699919799/utilities/⦠is the official standard for the command. From a POSIX view, $# is expected to be 0 in all cases (unless the shell implements an extension. In special, in your second example, $# is expected to be 0, except if you called your shell ac$shell -c 1a b c
.
â schily
May 4 at 10:06
I seem to be getting lots of explanations about why what I have done doesn't work, but no answers to tell me what I should do instead. Perhaps I didn't ask the question very well. I have edited my question to try and make it clearer what I am trying to do. Perhaps then someone can tell me how I should have coded my script.
â Morag Hughson
May 5 at 0:55
1
1
I think they are not passing arguments to
dot
yet the dotted script is picking up the existing args (which OP didnâÂÂt expect)â Jeff Schaller
May 3 at 17:46
I think they are not passing arguments to
dot
yet the dotted script is picking up the existing args (which OP didnâÂÂt expect)â Jeff Schaller
May 3 at 17:46
When I pass parameters to my script, e.g.
. ./myscript.sh a b c
it works fine. My question is about when I don't pass parameters.â Morag Hughson
May 3 at 21:43
When I pass parameters to my script, e.g.
. ./myscript.sh a b c
it works fine. My question is about when I don't pass parameters.â Morag Hughson
May 3 at 21:43
pubs.opengroup.org/onlinepubs/9699919799/utilities/⦠is the official standard for the command. From a POSIX view, $# is expected to be 0 in all cases (unless the shell implements an extension. In special, in your second example, $# is expected to be 0, except if you called your shell ac
$shell -c 1a b c
.â schily
May 4 at 10:06
pubs.opengroup.org/onlinepubs/9699919799/utilities/⦠is the official standard for the command. From a POSIX view, $# is expected to be 0 in all cases (unless the shell implements an extension. In special, in your second example, $# is expected to be 0, except if you called your shell ac
$shell -c 1a b c
.â schily
May 4 at 10:06
I seem to be getting lots of explanations about why what I have done doesn't work, but no answers to tell me what I should do instead. Perhaps I didn't ask the question very well. I have edited my question to try and make it clearer what I am trying to do. Perhaps then someone can tell me how I should have coded my script.
â Morag Hughson
May 5 at 0:55
I seem to be getting lots of explanations about why what I have done doesn't work, but no answers to tell me what I should do instead. Perhaps I didn't ask the question very well. I have edited my question to try and make it clearer what I am trying to do. Perhaps then someone can tell me how I should have coded my script.
â Morag Hughson
May 5 at 0:55
add a comment |Â
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f441515%2fparameters-passed-to-a-sourced-script-are-wrong%23new-answer', 'question_page');
);
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Possible duplicate of Passing variables to a bash script when sourcing it
â Patrick
May 3 at 12:05
3
This should work. Which shell are you using? Post a small, complete pair of scripts (the sourcing script and the sourced script) that reproduces the problem.
â Gilles
May 3 at 12:25
@Patrick That's not a duplicate: it explains that what Morag is trying to do should work.
â Gilles
May 3 at 12:26
@Gilles - I don't understand what you mean by a "pair of scripts". There is only one script which I run from the command line with the command shown in my question
. ./myscript.sh
. If I don't provide any parameters, e.g.. ./myscript.sh abc
then the script runs with parameters from a previously sourced command.â Morag Hughson
May 3 at 21:32
I seem to be getting lots of explanations about why what I have done doesn't work, but no answers to tell me what I should do instead. Perhaps I didn't ask the question very well. I have edited my question to try and make it clearer what I am trying to do. Perhaps then someone can tell me how I should have coded my script.
â Morag Hughson
May 5 at 0:55