3

I have a simple shell script to check if the user exist, if not, add that user

#!/usr/bin/bash
echo "Enter user"
read -r user
if [ "$(id -u "$user" &>/dev/null)" = 1 ]; then
  echo "user existed"
else
  useradd "$user"
  echo "add password"
  passwd "$user"
  echo "$user" &>>text.txt
  echo "saved"
fi

But it does not display the "echo user exist". instead it displays like so:

Enter user

abcdef

useradd: user 'abcdef' already exists

add password

New password: 

In this case abcdef is an existing user

Please let me know what goes wrong here, thanks a lot.

7
  • 2
    A tip to troubleshoot, run the command id -u testuser and check if the result is 1. Because 1 is the only thing that will proceed to echo "User exists"
    – MatsK
    Aug 27, 2021 at 23:22
  • 1
    @MatsK Even 1 won't proceed, as the output from id is redirected to /dev/null.
    – raj
    Aug 27, 2021 at 23:53
  • After your check of id -u $user &>/dev/null use echo $? and that will produce either a 0 or 1. 0 meaning exit code 0 or true, 1 meaning exit code 1 or false. Or you can have if [[ $? == 0 ]]; then, etc.
    – Terrance
    Aug 27, 2021 at 23:53
  • @Terrance It's simpler just to use id -u $user &>/dev/null straight away as condition in if.
    – raj
    Aug 27, 2021 at 23:55
  • @raj not in every case. Actually doing it with case statements works very well. The id -u produces the user ID number and not a 1 or 0. So, outputting id -u to >/dev/null will get rid of the 1000 if that is the user ID.
    – Terrance
    Aug 27, 2021 at 23:56

2 Answers 2

9

The following condition in your script:

if [ "$(id -u "$user" &>/dev/null)" = 1 ]; then

will never be true. It would be true only if the output of command id -u "$user" &>/dev/null would be the single digit 1, but as any output from that command is redirected to /dev/null, this will never happen.

Replace that line with

if { id -u "$user" &>/dev/null ; } then

This condition checks the exit status of the command (and not its output like $(...) does) and will be true if the command id -u "$user" &>/dev/null succeeds (that is, user exists) and false if it fails (that is, user doesn't exist).

6
  • Thank for your answer, it work!!v But what different between [] and {}? Aug 27, 2021 at 22:32
  • 2
    [ is a command (equivalent to test; see man [) used to check the result of various conditional expressions. {} are just parentheses to enclose the command. Actually, we may skip {} altogether (while you cannot skip []): if id -u "$user" &>/dev/null ; then will work as well only is less readable.
    – raj
    Aug 27, 2021 at 22:59
  • i sitll dont understand [ is a command to check the value, then, in my command '"$(id -u "$user" &>/dev/null)" = 1` why it not return true, i mean, "$(id -u "$user" &>/dev/null)" will return 0 or 1 right? Aug 27, 2021 at 23:44
  • 1
    The value of $(command) is the output of the command, ie. the text the command prints. Because you redirect that output to /dev/null, the command prints nothing. So the value of $(id -u "$user" &>/dev/null) will be always an empty string. You compare that empty string to the digit 1, which can never return true.
    – raj
    Aug 27, 2021 at 23:46
  • The { and } are superfluous. if id -u "$user" &>/dev/null; then is enough.
    – Jan Hudec
    Aug 28, 2021 at 19:19
2

The answer by @raj is 100% correct for simplifying code.

These are just some alternate ways of using the exit codes and maybe shedding a little more light in how they can be used.

The exit code can be checked by doing an echo $? right after your command of id -u $user &>/dev/null which doesn't need to be encased in $(..) or anything like that.

Just try id -u <username> &>/dev/null and then type in echo $? to check the exit code.

Example:

terrance@terrance-ubuntu:~$ id -u terrance &>/dev/null
terrance@terrance-ubuntu:~$ echo $?
0
terrance@terrance-ubuntu:~$ id -u mark &>/dev/null
terrance@terrance-ubuntu:~$ echo $?
1

In the above example, the user mark does not exist on my computer thus the exit status of 1.

Using the exit code you can put it into a case statement instead of an if..else statement.

#!/bin/bash
echo "Enter username"
read -r user
id -u "$user" &>/dev/null
case $? in
    0) echo "User exists";;
    1) adduser $user
       echo "add password"
       passwd $user
       echo $user >> text.txt
       echo "saved";;
esac

Interestingly enough, using an if [ ]; then can still be used as well by adding an echo $? into your if check, but I did notice that you were checking for 1 to be if exist, but 1 means that the code exited with 1 meaning not found.

Adding it will work like this as well.

#!/bin/bash
echo "Enter username"
read -r user
if [ $(id -u "$user" &>/dev/null; echo $?) == 0 ]; then
    echo "User exists"
else
    adduser $user
    echo "add password"
    passwd $user
    echo $user >> text.txt
    echo "saved"
fi
12
  • Thank, i learn a lot from your answer, but i dont understand why echo $ ,what is that ?? Aug 28, 2021 at 0:44
  • 1
    @LêQuốcKhánh Maybe this here might shed a little more light on the echo $? for checking exit commands: askubuntu.com/questions/646526/what-is-is-it-a-variable
    – Terrance
    Aug 28, 2021 at 0:45
  • 2
    @LêQuốcKhánh Using /dev/null is a way to basically erase the stdout from you seeing it on the screen. It is just a way to keep the stuff clean. You can get the same exit code or status without using it, but you will see all that output to the screen and it might make it more difficult to use your code. Feel free to test your code without the &>/dev/null as it should still work.
    – Terrance
    Aug 28, 2021 at 0:56
  • 1
    @LêQuốcKhánh The 0 and 1 is only the exit status. If you run id -u $user without anything after it, it will produce the user ID number. Like my username produces 1000 as that is my user ID number. But, if I type in echo $? after that command it will still produce a 0 since the exit status passed.
    – Terrance
    Aug 28, 2021 at 0:58
  • 1
    @LêQuốcKhánh id -u produces the UID or the user ID number not the exit status. You have to run echo $? as the next command to see what the exit status of the command id -u is.
    – Terrance
    Aug 28, 2021 at 2:27

You must log in to answer this question.

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