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

1 Answers1

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
Kusalananda
  • 333,661
  • ok, i will give it a try, but then this command wont give me a duplicate user from who command right? – Prin Puyakul Oct 06 '17 at 06:34
  • @PrinPuyakul I'm not sure what command you refer to or what you mean. – Kusalananda Oct 06 '17 at 06:42
  • i mean who | awk '{ print $1 }' | sort | uniq -d, sorry for my bad English communication skill haha – Prin Puyakul Oct 06 '17 at 06:51
  • @PrinPuyakul That command should give you the duplicated usernames that the who command outputs. – Kusalananda Oct 06 '17 at 06: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 06 '17 at 06:57
  • @dessert, I see, thanks so much for your answer i will try to understand how it work ^^", – Prin Puyakul Oct 06 '17 at 10:43
  • @Kusalananda ok, I will try those out and let u know the result, thanks a lot for your help again ^^: – Prin Puyakul Oct 06 '17 at 10:43
  • @Kusalananda

    I tested the script its working ok but if [ "$dupe" -ne 1 ]; then echo 'No dupes' fi it always get execute ?_? And another question I would like to ask, if i want to insert the result from who | awk '{ print $1 }' | sort in to a file and do the check from that file. how do i achieve that? do i just who | awk '{ print $1 }' | sort > list then at the end of the while loop i just done < list or i just only need done < list at the end? Thanks a lot in advance

    – Prin Puyakul Oct 07 '17 at 03:04
  • @PrinPuyakul I had two errors in the last bit of code that I now have fixed. A test was inverted (leftover from an edit), and the test on "$dupe" -ne 1 would always be true, as you pointed out (I fell into this trap, because I was running the code in ksh93 rather than sh or bash). I've updated the code to write to a temporary file. Sorry for any confusion! – Kusalananda Oct 07 '17 at 06:07
  • @Kusalananda No worry! you are always help out and i always learn something from you ! thanks a lot for your help, I will explain my knowledge into other script as well so know I will know the different from syntax like you and dessert point out about [[ ]] syntax – Prin Puyakul Oct 07 '17 at 06:28