What do the following environment variables in Linux mean?

  1. What is $* (dollar sign followed by an asterisk)?
  2. What is $# (dollar sign next to a hash mark/number sign/octothorpe/pound sign)?

2 Answers 2


From here:

$#    Stores the number of command-line arguments that 
      were passed to the shell program.
$?    Stores the exit value of the last command that was 
$0    Stores the first word of the entered command (the 
      name of the shell program).
$*    Stores all the arguments that were entered on the
      command line ($1 $2 ...).
"$@"  Stores all the arguments that were entered
      on the command line, individually quoted ("$1" "$2" ...).

So basically, $# is a number of arguments given when your script was executed. $* is a string containing all arguments. For example, $1 is the first argument and so on. This is useful, if you want to access a specific argument in your script.

As Brian commented, here is a simple example. If you run following command:

./command -yes -no /home/username
  • $# = 3
  • $* = -yes -no /home/username
  • $@ = array: {"-yes", "-no", "/home/username"}
  • $0 = ./command, $1 = -yes etc.

These are part of POSIX standard, and should be supported by all compliant shells. For the reference, below is POSIX standard definitions for each special parameter. Do note there's three additional variables: $-, $$ and $!.


Expands to the positional parameters, starting from one. When the expansion occurs within double-quotes, and where field splitting (see Field Splitting) is performed, each positional parameter shall expand as a separate field, with the provision that the expansion of the first parameter shall still be joined with the beginning part of the original word (assuming that the expanded parameter was embedded within a word), and the expansion of the last parameter shall still be joined with the last part of the original word. If there are no positional parameters, the expansion of '@' shall generate zero fields, even when '@' is double-quoted.


Expands to the positional parameters, starting from one. When the expansion occurs within a double-quoted string (see Double-Quotes), it shall expand to a single field with the value of each parameter separated by the first character of the IFS variable, or by a if IFS is unset. If IFS is set to a null string, this is not equivalent to unsetting it; its first character does not exist, so the parameter values are concatenated.


Expands to the decimal number of positional parameters. The command name (parameter 0) shall not be counted in the number given by '#' because it is a special parameter, not a positional parameter.


Expands to the decimal exit status of the most recent pipeline (see Pipelines).


(Hyphen.) Expands to the current option flags (the single-letter option names concatenated into a string) as specified on invocation, by the set special built-in command, or implicitly by the shell.


Expands to the decimal process ID of the invoked shell. In a subshell (see Shell Execution Environment ), '$' shall expand to the same value as that of the current shell.


Expands to the decimal process ID of the most recent background command (see Lists) executed from the current shell. (For example, background commands executed from subshells do not affect the value of "$!" in the current shell environment.) For a pipeline, the process ID is that of the last command in the pipeline.


(Zero.) Expands to the name of the shell or shell script. See sh for a detailed description of how this name is derived.

  • 1
    Those special parameters are true in all Bourne-derived shells (e.g. sh, bash, dash, ash, ksh, zsh). Feb 17, 2011 at 19:10
  • Correction: $* and $# are 1) shell variables, not environment variables; 2) standardized (part of the POSIX spec.) Feb 17, 2011 at 19:11
  • 3
    Also notice that "$@" many times is written as ${1+"$@"} (for portability reasons), see stackoverflow.com/questions/743454/… for an explanation.
    – hlovdal
    Feb 17, 2011 at 19:55
  • Since 'The command name (parameter 0) shall not be counted...', in the example above should be $# = 2, starting counting from 0. Jun 13, 2018 at 5:02

$# represents the number of arguments:

[root@baymax ~]# set -- a
[root@baymax ~]# echo $#

[root@baymax ~]# set -- a b c
[root@baymax ~]# echo $#
  • 2
    Welcome to Super User. The site is a knowledge base, so the intent is that each answer provide a solution to the question that has not already been contributed. This only addresses half of the question, and the information is already well covered in the previous answer.
    – fixer1234
    Sep 24, 2018 at 5:41

You must log in to answer this question.

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