The argument number variable does not count the inputed parameters [duplicate]












3
















This question already has an answer here:




  • Read Command : How to verify user has typed something

    3 answers



  • What does $# mean in shell?

    3 answers




I have the following script :



echo  'Please select type file , the name of the input file and the name of the output file:

a.plain ( please press a ) <input_file> <output_file>;
b.complex ( please press b ) <input_file> <output_file>;'

read one two three
echo $#

if [ $# -ne 3 ]; then
echo "Insufficient arguments !"
exit 1;
else
echo "Number of passed parameters is ok"
fi


$# always outputs 0 , the read command provides the correct variables when I am using $one , $two and $three later in the script



Thank you.










share|improve this question















marked as duplicate by RalfFriedl, Fabby, G-Man, maxschlepzig, Isaac Nov 24 '18 at 22:44


This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.



















  • A shell script must start with a #! line. If it's missing the kernel will refuse to execute the script. (There are shells which detect this error and attempt to work around it, but they aren't consistent about which interpreter to use. So you'll end up with very inconsistent behavior.)

    – kasperd
    Nov 23 '18 at 23:18
















3
















This question already has an answer here:




  • Read Command : How to verify user has typed something

    3 answers



  • What does $# mean in shell?

    3 answers




I have the following script :



echo  'Please select type file , the name of the input file and the name of the output file:

a.plain ( please press a ) <input_file> <output_file>;
b.complex ( please press b ) <input_file> <output_file>;'

read one two three
echo $#

if [ $# -ne 3 ]; then
echo "Insufficient arguments !"
exit 1;
else
echo "Number of passed parameters is ok"
fi


$# always outputs 0 , the read command provides the correct variables when I am using $one , $two and $three later in the script



Thank you.










share|improve this question















marked as duplicate by RalfFriedl, Fabby, G-Man, maxschlepzig, Isaac Nov 24 '18 at 22:44


This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.



















  • A shell script must start with a #! line. If it's missing the kernel will refuse to execute the script. (There are shells which detect this error and attempt to work around it, but they aren't consistent about which interpreter to use. So you'll end up with very inconsistent behavior.)

    – kasperd
    Nov 23 '18 at 23:18














3












3








3









This question already has an answer here:




  • Read Command : How to verify user has typed something

    3 answers



  • What does $# mean in shell?

    3 answers




I have the following script :



echo  'Please select type file , the name of the input file and the name of the output file:

a.plain ( please press a ) <input_file> <output_file>;
b.complex ( please press b ) <input_file> <output_file>;'

read one two three
echo $#

if [ $# -ne 3 ]; then
echo "Insufficient arguments !"
exit 1;
else
echo "Number of passed parameters is ok"
fi


$# always outputs 0 , the read command provides the correct variables when I am using $one , $two and $three later in the script



Thank you.










share|improve this question

















This question already has an answer here:




  • Read Command : How to verify user has typed something

    3 answers



  • What does $# mean in shell?

    3 answers




I have the following script :



echo  'Please select type file , the name of the input file and the name of the output file:

a.plain ( please press a ) <input_file> <output_file>;
b.complex ( please press b ) <input_file> <output_file>;'

read one two three
echo $#

if [ $# -ne 3 ]; then
echo "Insufficient arguments !"
exit 1;
else
echo "Number of passed parameters is ok"
fi


$# always outputs 0 , the read command provides the correct variables when I am using $one , $two and $three later in the script



Thank you.





This question already has an answer here:




  • Read Command : How to verify user has typed something

    3 answers



  • What does $# mean in shell?

    3 answers








bash shell-script






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 23 '18 at 7:53









ctrl-alt-delor

12.2k42561




12.2k42561










asked Nov 23 '18 at 7:48









bboybboy

274




274




marked as duplicate by RalfFriedl, Fabby, G-Man, maxschlepzig, Isaac Nov 24 '18 at 22:44


This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.









marked as duplicate by RalfFriedl, Fabby, G-Man, maxschlepzig, Isaac Nov 24 '18 at 22:44


This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.















  • A shell script must start with a #! line. If it's missing the kernel will refuse to execute the script. (There are shells which detect this error and attempt to work around it, but they aren't consistent about which interpreter to use. So you'll end up with very inconsistent behavior.)

    – kasperd
    Nov 23 '18 at 23:18



















  • A shell script must start with a #! line. If it's missing the kernel will refuse to execute the script. (There are shells which detect this error and attempt to work around it, but they aren't consistent about which interpreter to use. So you'll end up with very inconsistent behavior.)

    – kasperd
    Nov 23 '18 at 23:18

















A shell script must start with a #! line. If it's missing the kernel will refuse to execute the script. (There are shells which detect this error and attempt to work around it, but they aren't consistent about which interpreter to use. So you'll end up with very inconsistent behavior.)

– kasperd
Nov 23 '18 at 23:18





A shell script must start with a #! line. If it's missing the kernel will refuse to execute the script. (There are shells which detect this error and attempt to work around it, but they aren't consistent about which interpreter to use. So you'll end up with very inconsistent behavior.)

– kasperd
Nov 23 '18 at 23:18










3 Answers
3






active

oldest

votes


















7














To test whether you got values for all variables and exit otherwise, use the -z test to test for empty strings:



if [ -z "$one" ] || [ -z "$two" ] || [ -z "$three" ]; then
echo 'Did not get three values' >&2
exit 1
fi


The $# value is the number of positional parameters, usually command line arguments (or values set by the set builtin). These are available in $1, $2, $3, etc. (or collectively in the array "$@") and are unrelated to the values read by the read builtin.





To make your script take the input as command line arguments instead of reading them interactively (which may be preferred if the user is to supply one or several paths as they may take advantage of tab-completion, and it also makes it easier to use the script from within another script and does not require that there is a terminal connected), use



if [ "$#" -ne 3 ]; then
echo 'Did not get three command line arguments' >&2
exit 1
fi

one=$1
two=$2
three=$3


The script would in this case be run as



./script.sh a.plain /path/to/inputfile /path/to/outputfile




If the processing of the input can happen from standard input and if the output can be sent to standard output (i.e. if you don't actually need the explicit paths of the input file and output file inside the script), then the script only has to take the first parameter (a.plain or b.complex).



./script.sh a.plain </path/to/inputfile >/path/to/outputfile


The script would then use the standard input and standard output streams for input and output (and consequently only has to check for a single command line argument).



This would make it possible to run the script with data piped in from another program, and it would also allow for further post-processing:



gzip -dc <file-in.gz | ./script.sh a.plain | sort | gzip -c >file-out.gz





share|improve this answer

































    4














    What you are doing wrong



    You are confusing input arguments (to the script, at startup), and user input, using read (at run time).



    $# reports number of arguments at startup. e.g. for ./«script_name» 1 2 3, when used in the script, it will return 3.






    share|improve this answer































      0














      You can use the set command to re-set the positional arguments, overwriting the previous values. The IFS variable specifies the list of characters to be used as a separator, so you can also use that to parse CSV. Note that set is a builtin, so the usual syntax to override variables for single commands does not work, as variables specified before a command are a shorthand for the env command, which would set the environment for a subprocess.



      $# is the number of positional arguments that currently exist.



      $ read foo
      a b c d e
      $ echo $foo
      a b c d e
      $ set -- $foo
      $ echo $#
      5
      $ IFS=: set -- $foo # doesn't work
      $ echo $#
      5 # still got 5
      $ IFS=:
      $ set -- $foo
      $ echo $#
      1





      share|improve this answer






























        3 Answers
        3






        active

        oldest

        votes








        3 Answers
        3






        active

        oldest

        votes









        active

        oldest

        votes






        active

        oldest

        votes









        7














        To test whether you got values for all variables and exit otherwise, use the -z test to test for empty strings:



        if [ -z "$one" ] || [ -z "$two" ] || [ -z "$three" ]; then
        echo 'Did not get three values' >&2
        exit 1
        fi


        The $# value is the number of positional parameters, usually command line arguments (or values set by the set builtin). These are available in $1, $2, $3, etc. (or collectively in the array "$@") and are unrelated to the values read by the read builtin.





        To make your script take the input as command line arguments instead of reading them interactively (which may be preferred if the user is to supply one or several paths as they may take advantage of tab-completion, and it also makes it easier to use the script from within another script and does not require that there is a terminal connected), use



        if [ "$#" -ne 3 ]; then
        echo 'Did not get three command line arguments' >&2
        exit 1
        fi

        one=$1
        two=$2
        three=$3


        The script would in this case be run as



        ./script.sh a.plain /path/to/inputfile /path/to/outputfile




        If the processing of the input can happen from standard input and if the output can be sent to standard output (i.e. if you don't actually need the explicit paths of the input file and output file inside the script), then the script only has to take the first parameter (a.plain or b.complex).



        ./script.sh a.plain </path/to/inputfile >/path/to/outputfile


        The script would then use the standard input and standard output streams for input and output (and consequently only has to check for a single command line argument).



        This would make it possible to run the script with data piped in from another program, and it would also allow for further post-processing:



        gzip -dc <file-in.gz | ./script.sh a.plain | sort | gzip -c >file-out.gz





        share|improve this answer






























          7














          To test whether you got values for all variables and exit otherwise, use the -z test to test for empty strings:



          if [ -z "$one" ] || [ -z "$two" ] || [ -z "$three" ]; then
          echo 'Did not get three values' >&2
          exit 1
          fi


          The $# value is the number of positional parameters, usually command line arguments (or values set by the set builtin). These are available in $1, $2, $3, etc. (or collectively in the array "$@") and are unrelated to the values read by the read builtin.





          To make your script take the input as command line arguments instead of reading them interactively (which may be preferred if the user is to supply one or several paths as they may take advantage of tab-completion, and it also makes it easier to use the script from within another script and does not require that there is a terminal connected), use



          if [ "$#" -ne 3 ]; then
          echo 'Did not get three command line arguments' >&2
          exit 1
          fi

          one=$1
          two=$2
          three=$3


          The script would in this case be run as



          ./script.sh a.plain /path/to/inputfile /path/to/outputfile




          If the processing of the input can happen from standard input and if the output can be sent to standard output (i.e. if you don't actually need the explicit paths of the input file and output file inside the script), then the script only has to take the first parameter (a.plain or b.complex).



          ./script.sh a.plain </path/to/inputfile >/path/to/outputfile


          The script would then use the standard input and standard output streams for input and output (and consequently only has to check for a single command line argument).



          This would make it possible to run the script with data piped in from another program, and it would also allow for further post-processing:



          gzip -dc <file-in.gz | ./script.sh a.plain | sort | gzip -c >file-out.gz





          share|improve this answer




























            7












            7








            7







            To test whether you got values for all variables and exit otherwise, use the -z test to test for empty strings:



            if [ -z "$one" ] || [ -z "$two" ] || [ -z "$three" ]; then
            echo 'Did not get three values' >&2
            exit 1
            fi


            The $# value is the number of positional parameters, usually command line arguments (or values set by the set builtin). These are available in $1, $2, $3, etc. (or collectively in the array "$@") and are unrelated to the values read by the read builtin.





            To make your script take the input as command line arguments instead of reading them interactively (which may be preferred if the user is to supply one or several paths as they may take advantage of tab-completion, and it also makes it easier to use the script from within another script and does not require that there is a terminal connected), use



            if [ "$#" -ne 3 ]; then
            echo 'Did not get three command line arguments' >&2
            exit 1
            fi

            one=$1
            two=$2
            three=$3


            The script would in this case be run as



            ./script.sh a.plain /path/to/inputfile /path/to/outputfile




            If the processing of the input can happen from standard input and if the output can be sent to standard output (i.e. if you don't actually need the explicit paths of the input file and output file inside the script), then the script only has to take the first parameter (a.plain or b.complex).



            ./script.sh a.plain </path/to/inputfile >/path/to/outputfile


            The script would then use the standard input and standard output streams for input and output (and consequently only has to check for a single command line argument).



            This would make it possible to run the script with data piped in from another program, and it would also allow for further post-processing:



            gzip -dc <file-in.gz | ./script.sh a.plain | sort | gzip -c >file-out.gz





            share|improve this answer















            To test whether you got values for all variables and exit otherwise, use the -z test to test for empty strings:



            if [ -z "$one" ] || [ -z "$two" ] || [ -z "$three" ]; then
            echo 'Did not get three values' >&2
            exit 1
            fi


            The $# value is the number of positional parameters, usually command line arguments (or values set by the set builtin). These are available in $1, $2, $3, etc. (or collectively in the array "$@") and are unrelated to the values read by the read builtin.





            To make your script take the input as command line arguments instead of reading them interactively (which may be preferred if the user is to supply one or several paths as they may take advantage of tab-completion, and it also makes it easier to use the script from within another script and does not require that there is a terminal connected), use



            if [ "$#" -ne 3 ]; then
            echo 'Did not get three command line arguments' >&2
            exit 1
            fi

            one=$1
            two=$2
            three=$3


            The script would in this case be run as



            ./script.sh a.plain /path/to/inputfile /path/to/outputfile




            If the processing of the input can happen from standard input and if the output can be sent to standard output (i.e. if you don't actually need the explicit paths of the input file and output file inside the script), then the script only has to take the first parameter (a.plain or b.complex).



            ./script.sh a.plain </path/to/inputfile >/path/to/outputfile


            The script would then use the standard input and standard output streams for input and output (and consequently only has to check for a single command line argument).



            This would make it possible to run the script with data piped in from another program, and it would also allow for further post-processing:



            gzip -dc <file-in.gz | ./script.sh a.plain | sort | gzip -c >file-out.gz






            share|improve this answer














            share|improve this answer



            share|improve this answer








            edited Nov 23 '18 at 8:57

























            answered Nov 23 '18 at 8:13









            KusalanandaKusalananda

            138k17258428




            138k17258428

























                4














                What you are doing wrong



                You are confusing input arguments (to the script, at startup), and user input, using read (at run time).



                $# reports number of arguments at startup. e.g. for ./«script_name» 1 2 3, when used in the script, it will return 3.






                share|improve this answer




























                  4














                  What you are doing wrong



                  You are confusing input arguments (to the script, at startup), and user input, using read (at run time).



                  $# reports number of arguments at startup. e.g. for ./«script_name» 1 2 3, when used in the script, it will return 3.






                  share|improve this answer


























                    4












                    4








                    4







                    What you are doing wrong



                    You are confusing input arguments (to the script, at startup), and user input, using read (at run time).



                    $# reports number of arguments at startup. e.g. for ./«script_name» 1 2 3, when used in the script, it will return 3.






                    share|improve this answer













                    What you are doing wrong



                    You are confusing input arguments (to the script, at startup), and user input, using read (at run time).



                    $# reports number of arguments at startup. e.g. for ./«script_name» 1 2 3, when used in the script, it will return 3.







                    share|improve this answer












                    share|improve this answer



                    share|improve this answer










                    answered Nov 23 '18 at 7:59









                    ctrl-alt-delorctrl-alt-delor

                    12.2k42561




                    12.2k42561























                        0














                        You can use the set command to re-set the positional arguments, overwriting the previous values. The IFS variable specifies the list of characters to be used as a separator, so you can also use that to parse CSV. Note that set is a builtin, so the usual syntax to override variables for single commands does not work, as variables specified before a command are a shorthand for the env command, which would set the environment for a subprocess.



                        $# is the number of positional arguments that currently exist.



                        $ read foo
                        a b c d e
                        $ echo $foo
                        a b c d e
                        $ set -- $foo
                        $ echo $#
                        5
                        $ IFS=: set -- $foo # doesn't work
                        $ echo $#
                        5 # still got 5
                        $ IFS=:
                        $ set -- $foo
                        $ echo $#
                        1





                        share|improve this answer




























                          0














                          You can use the set command to re-set the positional arguments, overwriting the previous values. The IFS variable specifies the list of characters to be used as a separator, so you can also use that to parse CSV. Note that set is a builtin, so the usual syntax to override variables for single commands does not work, as variables specified before a command are a shorthand for the env command, which would set the environment for a subprocess.



                          $# is the number of positional arguments that currently exist.



                          $ read foo
                          a b c d e
                          $ echo $foo
                          a b c d e
                          $ set -- $foo
                          $ echo $#
                          5
                          $ IFS=: set -- $foo # doesn't work
                          $ echo $#
                          5 # still got 5
                          $ IFS=:
                          $ set -- $foo
                          $ echo $#
                          1





                          share|improve this answer


























                            0












                            0








                            0







                            You can use the set command to re-set the positional arguments, overwriting the previous values. The IFS variable specifies the list of characters to be used as a separator, so you can also use that to parse CSV. Note that set is a builtin, so the usual syntax to override variables for single commands does not work, as variables specified before a command are a shorthand for the env command, which would set the environment for a subprocess.



                            $# is the number of positional arguments that currently exist.



                            $ read foo
                            a b c d e
                            $ echo $foo
                            a b c d e
                            $ set -- $foo
                            $ echo $#
                            5
                            $ IFS=: set -- $foo # doesn't work
                            $ echo $#
                            5 # still got 5
                            $ IFS=:
                            $ set -- $foo
                            $ echo $#
                            1





                            share|improve this answer













                            You can use the set command to re-set the positional arguments, overwriting the previous values. The IFS variable specifies the list of characters to be used as a separator, so you can also use that to parse CSV. Note that set is a builtin, so the usual syntax to override variables for single commands does not work, as variables specified before a command are a shorthand for the env command, which would set the environment for a subprocess.



                            $# is the number of positional arguments that currently exist.



                            $ read foo
                            a b c d e
                            $ echo $foo
                            a b c d e
                            $ set -- $foo
                            $ echo $#
                            5
                            $ IFS=: set -- $foo # doesn't work
                            $ echo $#
                            5 # still got 5
                            $ IFS=:
                            $ set -- $foo
                            $ echo $#
                            1






                            share|improve this answer












                            share|improve this answer



                            share|improve this answer










                            answered Nov 23 '18 at 15:08









                            Simon RichterSimon Richter

                            2,5091213




                            2,5091213















                                Popular posts from this blog

                                "Incorrect syntax near the keyword 'ON'. (on update cascade, on delete cascade,)

                                Alcedinidae

                                RAC Tourist Trophy