What does $# mean in bash? (2025)

$# is the number of arguments, but remember it will be different in a function.

$# is the number of positional parameters passed to the script, shell, or shell function. This is because, while a shell function is running, the positional parameters are temporarily replaced with the arguments to the function. This lets functions accept and use their own positional parameters.

This script always prints 3, regardless of how many arguments were passed to the script itself, because "$#" in the function f expands to the number of arguments passed to the function:

#!/bin/shf() { echo "$#"}f a b c

This is important because it means code like this does not work as you might expect, if you're not familiar with how positional parameters work in shell functions:

#!/bin/shcheck_args() { # doesn't work! if [ "$#" -ne 2 ]; then printf '%s: error: need 2 arguments, got %d\n' "$0" "$#" >&2 exit 1 fi}# Maybe check some other things...check_args# Do other stuff...

In check_args, $# expands to the number of arguments passed to the function itself, which in that script is always 0.

If you want such functionality in a shell function, you'd have to write something like this instead:

#!/bin/shcheck_args() { # works -- the caller must pass the number of arguments received if [ "$1" -ne 2 ]; then printf '%s: error: need 2 arguments, got %d\n' "$0" "$1" >&2 exit 1 fi}# Maybe check some other things...check_args "$#"

This works because $# is expanded outside the function and passed to the function as one of its positional parameters. Inside the function, $1 expands to the first positional parameter that was passed to the shell function, rather than to the script it's part of.

Thus, like $#, the special parameters $1, $2, etc., as well as $@ and $*, also pertain to the arguments passed to a function, when they are expanded in the function. However, $0 does not change to the name of the function, which is why I was still able to use it to produce a quality error message.

$ ./check-args-demo a b c./check-args-demo: error: need 2 arguments, got 3

Similarly, if you define one function inside another, you're working with the positional parameters passed to the innermost function in which the expansion is performed:

#!/bin/shouter() { inner() { printf 'inner() got %d arguments\n' "$#" } printf 'outer() got %d arguments\n' "$#" inner x y z}printf 'script got %d arguments\n' "$#"outer p q

I called this script nested and (after running chmod +x nested) I ran it:

$ ./nested ascript got 1 argumentsouter() got 2 argumentsinner() got 3 arguments

Yes, I know. "1 arguments" is a pluralization bug.

The positional parameters can also be changed.

If you're writing a script, the positional parameters outside a function will be the command-line arguments passed to the script unless you have changed them.

One common way to change them is with the shift builtin, which shifts each positional parameter to the left by one, dropping the first one and decreasing $# by 1:

#!/bin/shwhile [ "$#" -ne 0 ]; do printf '%d argument(s) remaining.\nGot "%s".\n\n' "$#" "$1" shiftdone
$ ./do-shift foo bar baz # I named the script do-shift.3 argument(s) remaining.Got "foo".2 argument(s) remaining.Got "bar".1 argument(s) remaining.Got "baz".

They can also be changed with the set builtin:

#!/bin/shprintf '%d args: %s\n' "$#" "$*"set foo bar bazprintf '%d args: %s\n' "$#" "$*"
$ ./set-args a b c d e # I named the script set-args.5 args: a b c d e3 args: foo bar baz
What does $# mean in bash? (2025)

References

Top Articles
Latest Posts
Recommended Articles
Article information

Author: Amb. Frankie Simonis

Last Updated:

Views: 5652

Rating: 4.6 / 5 (76 voted)

Reviews: 91% of readers found this page helpful

Author information

Name: Amb. Frankie Simonis

Birthday: 1998-02-19

Address: 64841 Delmar Isle, North Wiley, OR 74073

Phone: +17844167847676

Job: Forward IT Agent

Hobby: LARPing, Kitesurfing, Sewing, Digital arts, Sand art, Gardening, Dance

Introduction: My name is Amb. Frankie Simonis, I am a hilarious, enchanting, energetic, cooperative, innocent, cute, joyous person who loves writing and wants to share my knowledge and understanding with you.