Adriano_Pinaffo
Adriano_Pinaffo

Reputation: 1699

Bash: To find length of all arguments passed

I want to find the length of all my arguments passed to a script. If I do this: echo ${#1} I see the length of my first argument, and if I do this: echo $* I see all my arguments separated by spaces. So, why doesn't it work to do this: echo ${#*}? Instead this show me the number of arguments passed, as if it was echo $#.

Is there a way to echo the total length without writing the value of $* to a new variable ($allargs=$*) and then checking the length of the new variable (echo ${#allargs})?

Upvotes: 2

Views: 1803

Answers (2)

user8017719
user8017719

Reputation:

Well, yes, the simplest method is:

$ IFS=''; a=$*; echo "${#a}"

Yes, there is no way to avoid a variable ($a) as the variable (parameter) is needed to be able to perform a "parameter expansion" (${#…}).

That, above, measure the length (in UNICODE code points in bash) of the strings in $@.
Use LC_ALL=C to count bytes.

If you need to place "an space" between each string (assuming the first character of IFS is an space, as it is by default):

$ a=$*; echo "${#a}"

Or, to be explicit:

$ IFS=' '; a=$*; echo "${#a}"

That, of course, change the value of $IFS. There are two ways to avoid that:

A subshell

$ ( IFS=' '; a=$*; echo "${#a}" )

A delay with eval:

$ IFS=' ' eval 'a=$*'; echo "${#a}"

For byte counting:

$ ( LC_ALL=C; IFS=' '; a=$*; echo "${#a}" )
$ LC_ALL=C IFS=' ' eval 'a=$*'; echo "${#a}"

Yes, yes, eval is safe in this case.

And no, arithmetic tricks will not make the answer simple:

$ set --  one two t33; a=$*; echo "$((${#a}-$#+1))"
9

Fail with an empty "$@":

$ set --             ; a=$*; echo "$((${#a}-$#+1))"
1

Upvotes: 1

Cyrus
Cyrus

Reputation: 88583

Sum the length of the arguments:

#!/bin/bash

declare -i length             # set integer attribute

for i in "${@}"; do length+=${#i}; done
echo $length

Upvotes: 1

Related Questions