2

I have a question about my code. I'm writing a Bourne shell script that get a user list from server by who command then put it into a file then, it will check the name by read line and if the script found a duplicate name it will print out a warning msg with the username, otherwise it will print out that no duplication found. Everything working as it should when the script found the duplicate name, but when the script can not find any duplicate name it will not print anything, I know it is something to do with the last if statement but I try so many solutions but still stuck. If anyone have any suggestion please help me out. Really appreciated and answer in advance. ( see the code below )

    #!/bin/sh
    #who -u | sort -k1,5 > test3
    log=~/Desktop/test3
        while [ -f test ]; do
          while IFS= read line; do
           user=( $line )

            if [ "$olduser" = "${user[0]}" ]; then
              printf '\nThe user %s duplicated' "$olduser"
            fi

           olduser="${user[0]}"
          done<"$log"

            if [[ "$olduser" != "${user[0]}" ]]; then
              printf '\nNo duplication found.\n';
            fi


            #Testing store value                       
            #printf '\nolduser value = %s\n' "$olduser" 
           printf '\n=================================================================\n'
sleep 3
done
  • Which shell are you using? – dessert Oct 6 '17 at 6:20
  • @dessert Bourne shell, =) – Prin Puyakul Oct 6 '17 at 6:21
  • I recommend shellcheck.net, for example for line 3 it outputs SC2039: In POSIX sh, arrays are undefined. and in line 12 In POSIX sh, [[ ]] is undefined – if you really want to use sh, only use code it understands. – dessert Oct 6 '17 at 6:25
2

Your code uses at least two things that standard sh does not support:

  1. [[ ... ]], this is an extension to the POSIX grammar that e.g. bash uses to introduce its own conditional expressions.

  2. user=( $line ), this creates an array, which is another extension to the POSIX sh.


To find the duplicated lines in a text file:

sort file | uniq -d

sort will sort the input file and uniq -d will only output lines that occur multiple times in succession.

To use this on the output of who and only care about the user column (the first column):

who | awk '{ print $1 }' | sort | uniq -d

Using this in a script:

who | awk '{ print $1 }' | sort | uniq -d >duplicates.txt

if [ -s duplicates.txt ]; then
    echo 'The following dupes were found:'
    cat duplicates.txt
else
    echo 'No dupes'
fi

The -s test will be true for a non-empty file.


To do it manually in the shell, set a flag when you've found a duplicate:

dupe=0

who | awk '{ print $1 }' | sort -o users.txt

while IFS= read -r user; do
    if [ -n "$prev_user" ] && [ "$user" = "$prev_user" ]; then
        printf 'Duplication for "%s"\n' "$user"
        dupe=1
    fi

    prev_user=$user
done <users.txt

if [ "$dupe" -ne 1 ]; then
    echo 'No dupes'
fi
  • ok, i will give it a try, but then this command wont give me a duplicate user from who command right? – Prin Puyakul Oct 6 '17 at 6:34
  • @PrinPuyakul I'm not sure what command you refer to or what you mean. – Kusalananda Oct 6 '17 at 6:42
  • i mean who | awk '{ print $1 }' | sort | uniq -d, sorry for my bad English communication skill haha – Prin Puyakul Oct 6 '17 at 6:51
  • @PrinPuyakul That command should give you the duplicated usernames that the who command outputs. – Kusalananda Oct 6 '17 at 6:56
  • So var=$(who | awk '{ print $1 }' | sort | uniq -d); [ "$var" ] && printf "\\nThe user %s is duplicated." $var || printf "\\nNo duplication found.\\n" does what your loop was supposed to do. – dessert Oct 6 '17 at 6:57

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.