why does this for loop only loop once? - bash

what i'm trying to do is a simple practice code with a output like this:
user1 logged in at hh:mm
user2 logged in at hh:mm
...
so i wrote a basic for loop, but what i don't understand why it only runs once.
for user in $(who)
do
USERID=$(echo $user | tr -s ' ' | cut -d' ' -f1)
LOGTIME=$(echo $user | tr -s ' '| cut -d' ' -f4)
echo "$USERID logged in at $LOGTIME"
done
this echos the following:
user1
user2
user3 logged in at hh:mm
hh:mm
hh:mm
i've put echo lines in between to figure out what is going on and how to fix it, but the only thing i figured out is that the for loop is only running once so USERID and LOGTIME is just a long string with linebreaks. what am i doing wrong? (i did the IFS=$ā€™\nā€™)

Would you please try the following:
while read -r user tty mon day logtime; do
echo "$user logged in at $logtime"
done < <(who)

#!/bin/sh
who > stack
while [ $(wc -l stack) -gt 0 ]
do
line=$(sed '1p' stack)
USERID=$(echo ${line} | tr -s ' ' | cut -d' ' -f1)
LOGTIME=$(echo ${line} | tr -s ' '| cut -d' ' -f4)
echo "${USERID} logged in at ${LOGTIME}"
sed -i '1d' stack
done
rm -v ./stack
exit 0
If this does not work, provide me with an example of who output on your machine.

Related

How do I fix my error saying the home directory is invalid?

I'm still learning how to work with bash but my program is part of part 1 which is posted below but they are wanting us to use the file cs.rosters.txt to generate the new_users.txt file.
The cs.rosters.txt looks like this:
CMPSC 1513 03|doejan|Doe, Jane|0510|0350
CMPSC 1513 03|smijoh|Smith, John|0510
CMPSC 1133 01|cp2stu3| CPII, Student3 Neither|2222|0020
Below is what I created for part 1 which runs correctly:
#!/bin/bash
while read -r line || [[ -n "$line" ]]; do
username=$(echo "$line" | cut -d: -f1)
GECOS=$(echo "$line" | cut -d: -f5)
homedir=$(echo "$line" | cut -d: -f6)
echo "adduser -g '$GECOS' -d '$homedir' -s /bin/bash '$username'"
done < "new_users.txt"
Here's where I'm struggling
The code above pretty much displays the information in the new_users.txt file
I'm struggling on the second part, my code is posted below:
What I want to do is create a script that generates the cs.rosters.txt file like I did above.
#!/bin/bash
while read line; do
user=$(echo $line | cut -d'|' -f2)
pass=$(echo $line | cut -d'|' -f3)
home=$(echo $line | cut -d'|' -f4)
useradd -m -d $home -s /bin/bash $user
echo $pass | passwd --stdin $user
done < cs_roster.txt
I'm getting two errors: one is saying the Computer directory is invalid and the function --stdin is invalid. Can you help me?

Using xargs parameterrs as variables to compare two md5sum

I'm extracting two md5sums by using this code:
md5sum test{1,2} | cut -d' ' -f1-2
I'm receiving two md5sums as in example below:
02eace9cb4b99519b49d50b3e44ecebc
d8e8fca2dc0f896fd7cb4cb0031ba249
Afterwards I'm not sure how to compare them. I have tried using the xargs:
md5sum test{1,2} | cut -d' ' -f1-2 | xargs bash -c '$0 == $1'
However, it tries to execute md5sum as a command
Any advice?
Try using a command subsitution instead
#!/bin/bash
echo 1 > file_a
echo 2 > file_b
echo 1 > file_c
file1=file_a
# try doing "file2=file_b" as well
file2=file_c
if [[ $(sha1sum $file1 | cut -d ' ' -f1-2) = $(sha1sum $file2 | cut -d ' ' -f1-2) ]]; then
echo same
else
echo different
fi

bash script, ask for arg if not provided

I have created a script that will check to see if a user you provide is logged on and display the duration of the session if logged on. What i need to do now is if no argument (username) is provided when the command is issued, ask for one and have the same results as if you have provided one.
Here is what I have:
name=$(cat /etc/passwd | grep $1 | cut -d':' -f5 | tr ':' ' ' | sed 's/,//' | sed 's/^\([^ ]*\) \([^ ]*\)/\2 \1/' | sort -t' ' -k3,3)
terminal=$(who | grep $1 | cut -d' ' -f3)
loginHour=$(who | grep $1 | cut -c30-31)
loginMin=$(who | grep $1 | cut -c33-34)
loginMins=$((loginHour * 60 + loginMin))
nowHour=$(date +%R | cut -c1-2)
nowMin=$(date +%R | cut -c4-5)
nowMins=$((nowHour * 60 + nowMin))
totalMins=$((nowMins - loginMins))
hoursOn=$((totalMins / 60))
minsOn=$((totalMins % 60))
clear
echo
if [[ $# -eq 1 ]] ; then
grep -q $1 /etc/passwd
if grep -q $1 /etc/passwd ; then
clear
echo
if who | grep $1 > /dev/null ; then
echo "$name" is currently logged on to terminal "$terminal" and has been for "$hoursOn" hour"(s)" and "$minsOn" minute"(s)".
echo
exit 0
else
echo "$name" is NOT currently logged on.
echo
exit 1
fi
else
echo The user you entered is not a valid user on this system.
echo
exit 2
fi
fi
I had an attempt before but was not the desired result so I removed it out of confusion.
if [[ $# -eq 0 ]]
then
read -p "Enter Name: " username
else
username=$1
fi
then replace all subsequent references to $1 by $username
You can also abort if no name given
# : does nothing it just forces the evaluation
: ${1:?"Need to provide name to script"}

How to concatenate comment + bash alias command call?

I'm trying to print out my ip address along with a comment in front of it. I have no idea how to do it all in one single line.
6 alias showip="ifconfig | grep 'inet' | sed -n '5p' | tr -s ' ' | cut -d ' ' -f2"
11 ip=showip
12 ip="ip: $ip"
13 echo ip
The output I'm looking for is something along the lines of:
ip: 192.168.1.2
Thanks a bunch guys.
printf 'ip: %s\n' $(showip)
UPDATED: PROBLEM SOLVED
I am not sure I understand your question but you may be looking for:
printf 'ip: %s\n' $(ifconfig | grep 'inet' | sed -n '5p' | tr -s ' ' | cut -d ' ' -f2)

How to reduce the use of `echo` in a bash script?

My bash script contains the following line:
echo $(echo "$STRING_VAR" | cut -d' ' -f 2) >> $FILE
Here we have two echo calls, but are they really necessary ?
I wrote them, because otherwise the bash would think the string in first place is a command.
Simply echo "$STRING_VAR" | cut -d' ' -f 2 >> $FILE does the same thing.
echo "$STRING_VAR" | cut -d' ' -f 2 >> $FILE
should be all you need
Also, bash has the handy "here-string" redirection mode: you don't need echo at all:
cut -d' ' -f2 <<< "$STRING_VAR" >> "$FILE"

Resources