Read loop from two files using descriptors

What I would like to do is read each line in the atdinfile:

A sample atdinfile would look like this:

651
652
653
654
655
656
657
658
659
660
661
664
665
666
667
668

I would like to grep through each atd job id looking for a match based on the input from another infile would is a listed of user groups:

A sample grplist file would look like this;

groupa
groupb
groupc
groupd
groupe

The code below will go through the list of atd jobs only once and try to match a corresponding line in the group file. This is not what I want. I want to grep for every group in each atd line before it moves onto the next atd job. Another problem is that the atd job list could be any number of lines whereas the grplist will tend to be static.

#!/bin/bash
set -x
ATDINFILE=/root/atdoutter.txt
DELTIMER=/root/delist.txt
USERNAME=ttimer
/usr/bin/atq | awk '{print $1}'|sort > $ATDINFILE
GRPLIST=/root/grouplist.txt
exec 3<$ATDINFILE
exec 4<$GRPLIST


while read atd <&3 && read grp <&4
do

at -c $atd|grep -wq "tmp-lock-ou.ldif."$USERNAME"" && at -c $atd | grep -wq "$grp"
 if [ $? -eq 0 ] ; then
   echo -e "${bldgrn}A $grp lock timer has been found for $USERNAME ${txtrst}" && echo "timer found for $USERNAME"
    sleep 1.5
    echo " "
     echo $atd | tee -a $DELTIMER >/dev/null 2>&1
      sleep 2
 fi
done < $ATDINFILE

Your while loop reads one line from each file and thus works on these pairs only. To have it compare/check the entire grplist file against every single job id, you need two nested loops, reading through the entire grplist file for every line in atdinfile. Or, you can use grep -f grpfile atdinfile .

Thanks for your reply.

I don't think the grep -f option will work in this case because I'm grepping on stdout from the at command and not to inside of a file during the loop.

Can you give me an example of how two nested loops might look like given this scenario?

You can grep -fgrplist on stdin from a pipe.

Nested loops look like e.g.

while read atd
   do while read grp
         do  your_commands
         done < GRPLIST
   done < ATDINFILE 

The outer loop reads the jobs one by one, and the inner does the comparisons for the entire grp file for every single job.

2 Likes

Thank you. I will give this a try.

Thanks again as this snippet got me on the right track..

Here's what I ended up using.

while read atdout; do

     while read accessgrp; do
        at -c $atdout | grep -wq "tmp-lock-ou.ldif."$USERNAME"" && at -c $atdout | grep -wq "$accessgrp"
            if [ $? -eq 0 ] ; then
               echo -e "${bldgrn}A $accessgrp lock timer has been found for $USERNAME ${txtrst}" && echo "Timer found for $USERNAME" > $TIMEROUT
                sleep 1.5
                  echo " "
                    echo -e "${bldylw}Displaying the current timer... ${txtrst}" && atq | grep $atdout | sed  's/^....//' |sed  's/......$//' | tee $LOCKTIME
                      sleep 3
                       echo " "
                       echo -e "${bldylw}Would you like to set a new timer for $USERNAME (yes/no)? ${txtrst}"
                       read input </dev/tty
                       if [[ $input = "yes" || $input = "YES" || $input = "y" || $input = "Y" ]]; then
                        echo $atdout | tee -a $DELTIMER >/dev/null 2>&1
                         do=enchilada
                         removetimer
                       elif [[ $input = "no" || $input = "NO" || $input = "n" || $input = "N" ]]; then
                         echo -e "${bldylw}Keeping old timer for $USERNAME ${txtrst}"
                          do=appetizer
                       else echo -e "${bldred}You entered an invalid option!${txtrst}"
                           cleanup
                       fi
            fi
     done < $GRPLIST
done < $ATDINFILE