1

I'm trying to count the number of HDD's on my linux system, I have put together the following line.

findhdds=$(find /sys/block -name 'sd*' | wc -l)

Now it seems to work when just running 'find /sys/block -name 'sd*' | wc -l' but when trying to store it in a variable I get the following message when reading it back:

3: command not found

Anyone understand where I have gone wrong?

twigg
  • 3,753
  • 13
  • 54
  • 96
  • What do you mean with "when reading it back"? You store it in a variable already. Does this message appear when you "echo" the variable "findhdds"? (Your code as such is correct; you might, just for the fun of it, provide absolute paths for find and wc - or, explicitely set the PATH variable so that "find" and "wc" will be found). – initall Oct 25 '12 at 08:45
  • Do you "read the variable back" with `echo $findhdds` ? – jens-na Oct 25 '12 at 08:47
  • yes sorry i meant when I echo it back – twigg Oct 25 '12 at 09:27
  • Please provide some sample code. There is nothing wrong with your command substitution. – initall Oct 25 '12 at 09:55
  • I think you left out the `echo` here. If you only type `$findhdds` in the shell you get something like `-bash: 3: command not found` because 1) the variable has the value `3` and 2) your shell tries to invoke a program named `3` . You should try: `echo $findhdds` instead. – jens-na Oct 25 '12 at 10:58

3 Answers3

3

If you store a command into a variable, calling this variable directly will execute the result. That's why it's trying to launch the command 3, which obviously doesn't exist. You have to print the variable to see the result: echo $findhdds

2

Explanation of bug

Some version/implementation of wc made formatted output and put spaces before the value you coud try:

$ wc -l < <(find /sys/block/ -name 'sd*')
  3

Please, note that output of wc contain spaces. Now try:

$ findhdds= 3
bash: 3: command not found

to obtain the error reported in SO's question.

Two solutions (and more...):

.1 compute answer to ensure this become a number:

findhdds=$((0+$(find /sys/block/ -name 'sd*' | wc -l)))

Or (I like this):

findhdds=$[$(find /sys/block/ -name 'sd*' | wc -l)]

Both of them will store number only in variable:

echo $findhdds 
3

.2 Store devices names in an array an count members:

You could use bash for doing what wc does:

$ findhdds=($(find /sys/block/ -name 'sd*'))

$ echo $findhdds
/sys/block/sda

$ echo ${#findhdds[@]}
3

$ echo ${findhdds[2]}
/sys/block/sdc

Pure

At all, in this particular case, you could use bash for the whole job:

Simply:

findhdds=(/sys/block/sd*)

Count

echo ${#findhdds[@]}
3

Indices

echo ${!findhdds[@]}
0 1 2

All disks (with full paths)

echo ${findhdds[@]}
/sys/block/sda /sys/block/sdb /sys/block/sdc

One of them

echo ${findhdds[0]}
/sys/block/sda

Only the device name

echo ${findhdds[0]##*/}
sda

echo ${findhdds[@]##*/}
sda sdb sdc

... could be processed in a loop:

for devnam in ${findhdds[@]##*/} ; do
    printf "Doing something with device: %s...\n" $devnam
  done
Doing something with device: sda...
Doing something with device: sdb...
Doing something with device: sdc...
F. Hauri - Give Up GitHub
  • 64,122
  • 17
  • 116
  • 137
-1

try this one:

findhdds=`find /sys/block/ -name 'sd*' | wc -l`

Hope this helps!

alan978
  • 535
  • 3
  • 6