Reputation: 1699
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
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
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