Parameters passed to a sourced script are wrong

The name of the pictureThe name of the pictureThe name of the pictureClash 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?







share|improve this question





















  • 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














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?







share|improve this question





















  • 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












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?







share|improve this question













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?









share|improve this question












share|improve this question




share|improve this question








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
















  • 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










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.






share|improve this answer























  • 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


















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.)






share|improve this answer























  • 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, 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










  • 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

















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





share|improve this answer



















  • 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










  • 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










Your Answer







StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "106"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);

else
createEditor();

);

function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
convertImagesToLinks: false,
noModals: false,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);



);








 

draft saved


draft discarded


















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






























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.






share|improve this answer























  • 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















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.






share|improve this answer























  • 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













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.






share|improve this answer















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.







share|improve this answer















share|improve this answer



share|improve this answer








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

















  • 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













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.)






share|improve this answer























  • 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, 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










  • 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














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.)






share|improve this answer























  • 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, 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










  • 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












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.)






share|improve this answer















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.)







share|improve this answer















share|improve this answer



share|improve this answer








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. 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










  • 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










  • @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










  • 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










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





share|improve this answer



















  • 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










  • 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














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





share|improve this answer



















  • 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










  • 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












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





share|improve this answer















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






share|improve this answer















share|improve this answer



share|improve this answer








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










  • 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




    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










  • 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












 

draft saved


draft discarded


























 


draft saved


draft discarded














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













































































Popular posts from this blog

How to check contact read email or not when send email to Individual?

Bahrain

Postfix configuration issue with fips on centos 7; mailgun relay