0

I am writing a code that takes in an integer in megabytes and I am meant to loop over the users in my machine and echo any user's name whose their home directory usage exceed over that amount in megabytes. Hence my strategy was take a number, convert it to megabytes from kilobytes, loop through everyone's home directory in my machine and echo their user name.

Hence my code below:

#!/bin/bash
#https://unix.stackexchange.com/questions/199220/how-to-loop-over-users

size=$(($1 * 1000000))
getent passwd | while IFS=: read -r name password uid gid gecos home shell; do
  du -sh $home | awk '{$1}'
  if [ $i -ge  size]
  then
    echo $name
  fi
done

the loop just loops through the users, which it does in isolation, the awk is meant to capture only the number for the disk usage which also seems to loop through all my directories and not having the permission to do so:

du: cannot read directory '/etc/vpnc': Permission denied
du: cannot read directory '/etc/credstore': Permission denied
du: cannot read directory '/etc/ssl/private': Permission denied

additionally when I do try to compare it to my disk usage limit:

if [ $i -ge  size]

it says this line was not found, is it since awk does not capture the size correctly and if so how would I compare the input vs the home direct or du size

7: [: missing ]

Thank you

2
  • 2
    The syntax for arithmetic evaluation is $(($1 * 1000000)) not $($1 * 1000000) - there are other errors, I suggest making use of www.shellcheck.net Oct 5, 2023 at 18:12
  • ... as well, while it's syntactically valid, I suspect you want awk '{print $1}' not awk '{$1}' Oct 5, 2023 at 18:23

1 Answer 1

1

It is normal to write a script only to find that it doesn't work. What you are missing here is basic troubleshooting. Here is the problem:

  • An unknown part of the script is broken.
  • You are trying to repair the script without locating which part is broken.

The strategy you require is a two-step process:

  • Find the simplest piece of code necessary to reproduce the error.
  • Fix the code to resolve that error.

Let's look at your first error message:

4: 20: not found

The 4: means line 4, so we want to check that line: size=$($1 * 1000000) Here you use the $1 syntax so I'll try putting the code in a bash function so I can call it with a parameter (and therefore use the same $1 syntax:

bash-3.2$ function test_code { size=$($1 * 1000000); }
bash-3.2$ test_code 20
bash: 20: command not found

Close enough (maybe you're using a different version of bash) - we have reproduced the error and now we can try to fix that code. A little bit of experience is helpful here as the 20: might be interpreted as a line number again. But actually it's just the value from the parameter:

bash-3.2$ test_code example
bash: example: command not found

The problem here is more obvious if you name a command that exists, like the date command:

bash-3.2$ test_code date
date: illegal time format
usage: date [-jnRu] [-I[date|hours|minutes|seconds]] [-f input_fmt]
            [-r filename|seconds] [-v[+|-]val[y|m|w|d|H|M|S]]
            [[[[mm]dd]HH]MM[[cc]yy][.SS] | new_date] [+output_fmt]

Your code isn't trying to multiply the parameter by 1000000, instead it is trying to treat that parameter as a command name and execute that command:

  • You expect the code to multiply two values together and store the result.
  • Instead the code is executing the given value as a command.

Therefore, you need to google "Multiply two values in bash". Google gave me this Unix & Linux question: Arithmetic in a bash script

And we see:

You can use $((expr)) notation to do that.

$ echo $((6 + 6))
12
$ echo $((6 * 6))
36

And if we compare this to our code the problem becomes apparent:

bash-3.2$ function test_code { echo $($1 * 1000000); }
bash-3.2$ test_code 20
bash: 20: command not found

Namely, echo $($1 * 1000000) uses only one pair of () parentheses and the example echo $((6 * 6)) code uses two. Let's see if we can fix this code:

bash-3.2$ function test_code { echo $(($1 * 1000000)); }
bash-3.2$ test_code 20
20000000

Line 4 of your script can now be updated to size=$(($1 * 1000000)) and you can move onto the next error to repeat the process.

2
  • thank you so much
    – Yemannasuk
    Oct 6, 2023 at 6:42
  • @Yemannasuk : Don't be afraid to "accept" the answer that solves your problem, AND you can also upvote any/all answers that helped shed light in resolving your problem.
    – shellter
    Oct 8, 2023 at 18:15

You must log in to answer this question.

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