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

10.9k41958




10.9k41958










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

            123k16232379




            123k16232379

























                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

                    10.9k41958




                    10.9k41958























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




                            2,4991113















                                Popular posts from this blog

                                Berounka

                                Sphinx de Gizeh

                                Different font size/position of beamer's navigation symbols template's content depending on regular/plain...