LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Linux - Newbie (https://www.linuxquestions.org/questions/linux-newbie-8/)
-   -   for loops, if statements (https://www.linuxquestions.org/questions/linux-newbie-8/for-loops-if-statements-741036/)

PAvandal 07-18-2009 12:12 PM

for loops, if statements
 
Hello everyone. This seems to be a great forum, I notice a lot of useful answers and help.

I am in the midst of taking a summer course dedicated to linux administration, and have hit a wall. We began studying scripting, and I thought I had a hold of it.. until the "for loops" and "if statements" came rolling in. Since we don't have a book to refer to, I decided to hit the web for help!

We have 3 scripts to write for homework. I can get the individual information for each, but I am stuck on how to link all of these commands together via ifs and for loops. I was ok in class with my professor guiding us, but I feel that his examples were extremely easier than what he assigned for homework.

so onto the problems.. er, scripts!

SCRIPT #1...

1. Write a script that take a list of users on the system and determine if the user is currently logged in, if the user is logged in display the time and date the user logged in, and list the files (just files, not directories) in the users home directory. If the user is not logged in simply print a message indicating that the user is not logged in.

Okay. I have been using

Code:

#!/bin/bash
users=`cat /etc/passwd | grep -v nologin | cut -d: -f1 | grep -v halt | grep -v shutdown | grep -v news | grep -v sync`

to find the list of regular users.

to find what users are logged in, I am using

Code:

who | grep -v pts
to get the list of users that are currently logged in and the times they logged in.

to find the files in the users home directory, I would use something like

Code:

home=`cat /etc/passwd | grep -v nologin | cut -d: -f6`
to find the home directory, and then something like

Code:

ls -l $home
to find the files in the directory.

Now... how in the heck do I put all that together?! I am seriously lost.

SCRIPT 2...


2. Write a script that will take 1 command line argument. The argument will be a username. The script will determine if the user exists on the system and will print an error if it does not. If the user does exist it will determine if the user is currently logged in, if the user is not logged in it will determine the last time the user logged in and display the file in the users home directory that was most recently modified.


This one has me utterly lost. ANY, I mean, ANY, help would be appreciated! :cool:

Thank you everyone. Now that I have access to linux knowledge, I believe I will be stopping by here a lot!

colucix 07-18-2009 12:45 PM

Hi and welcome to LQ!

Well, for script 1 use a for loop over the users stored in the variable "users". The syntax is quite easy:
Code:

for user in $users
do
  echo $user
done

Think that at each cycle you have just one user to manage and the loop variable "user" will be the one to use properly inside the cycle. Regarding the who command you can try the -u option to restrict the list to the actually logged users.

One thing to take in mind is that the shell does "expansions" before actually executing a command. In the example above, before the for loop is executed the shell expand the variable "users" to its actual value, resulting in something like:
Code:

for user in alex john arnold ted
do
  echo $user
done

To see the result of expansions and eventually debug your program, you can run it using
Code:

bash -x script.sh
so that the shell will print the expanded commands and help you in understanding how it works. Regarding shell expansion take alook here: http://tldp.org/LDP/Bash-Beginners-G...ect_03_04.html

Regarding script 2, I can't give the solution, since you have to figure it out by yourself in the learning process. Take in mind that arguments (usually called "positional parameters") are referred inside the script as $1, $2, $3... and so on. Even better if you use brackets, ${1}, ${2} and so on. In bash the brackets let you use more than 9 arguments, because $10 is an error, while ${10} is interpreted correctly.

Anyway, at the beginning of the script you can simply do:
Code:

#!/bin/bash
user=$1

so that you have a variable "user" to which you refer in the rest of the script as you do in script 1. Just a matter of variables names, since you can continue to use $1 in the whole script as well.

Finally, if you need some good text, you can bookmark the Advanced Bash Scripting Guide, a complete reference guide to all the bash basics and tricks. There is also a PDF available, you can download it but don't try to print it... they are hundreds of pages! ;)

pixellany 07-18-2009 01:01 PM

Welcome to LQ---and thank you for acknowledging that this is homework.

If they don't give you a book, where are you getting ANY information?----lecture notes? Head over to http://tldp.org and get the Bash Guide for Beginners by Machtelt Garrels. You might also want to get the Advanced Bash Scripting Guide. The latter is not a tutorial, but has a bazillion examples and is useful for searching.

If:
This is easy. The basic syntax is:
Code:

if <some test>
then
    do something
else
    do something different
fi

#EXAMPLE:
if [ $variable -gt 1 ]
then
    echo "it's bigger!!"
else
    echo "it's not bigger...."
fi

(The "else" is optional--ie you can do something if the test succeeds, and do nothing if it fails)

Loops:
There are two basic kinds---I'll describe each with an example. In this case, I'm putting them all on one line---you can cut and paste these to see how they work.


Code:

for i in $(seq 1 10); do echo $i; done


i=2; while [ $i -lt 7 ]; do echo $i; i=$(($i+1));done

#And of course the endless loop:
while true; do echo "we're running"; done

Note in this example that the ";" is functionally that same as a newline character.

catkin 07-18-2009 01:27 PM

Hello PAvandal :)

Welcome to the forum.

"Advanced Bash Scripting Guide" is good, especially for examples, but is not so easy to find you way around. It's one of the three I use for reference.

The others are Gnu's Bash Reference Manual (it has a great Table of Contents) and The Open Group's definition of the (POSIX) Shell Command Language (no Table of Contents but all on one page so easy to search. Very terse but tightly defined; useful when looking for a precise definition).

Best

Charles

PAvandal 07-18-2009 02:31 PM

Thank you everyone for your help and resources.

I think that the issue that I'm having is that I don't understand, in human terms, how to "test" things. in the if statements, what kind of commands or syntax are to be used to run my list of users against the list in the who command? I understand that this is function of the "if" statement.

Through everyone's help, I understand that each "user" will go through the loop on their own. I need a command that can check to see if each user that is in the $users variable are in the "who" command listing. My instructor told us that we could use the "test" command, but it seems to be a lot more complicated than something I can just put in my script.

pixellany - all of the information is from lecture. One of the problems is that it's a 4 hour class, and we cover a lot of material each class without any time to test what we have learned and see where we are failing. I'm very interested in all of this, but it's a rather daunting way to learn! :study:

mmatt 07-18-2009 02:50 PM

As with most programming problems there is more than one way to do this. You could use a nested for loop and an if statement to check the current user against the list from who - this would be quite inefficient. Or you could search for the user in the list with, for example, grep and use the return code or string length of the result as a value to test against. If you need a code example just ask, but have a go first.

p.s. use grep -w to match whole words

catkin 07-18-2009 03:29 PM

Quote:

Originally Posted by PAvandal (Post 3612016)
Thank you everyone for your help and resources.

I think that the issue that I'm having is that I don't understand, in human terms, how to "test" things. in the if statements, what kind of commands or syntax are to be used to run my list of users against the list in the who command? I understand that this is function of the "if" statement.

Through everyone's help, I understand that each "user" will go through the loop on their own. I need a command that can check to see if each user that is in the $users variable are in the "who" command listing. My instructor told us that we could use the "test" command, but it seems to be a lot more complicated than something I can just put in my script.

pixellany - all of the information is from lecture. One of the problems is that it's a 4 hour class, and we cover a lot of material each class without any time to test what we have learned and see where we are failing. I'm very interested in all of this, but it's a rather daunting way to learn! :study:

You are already looping over all the users in the passwd file and you have a list of logged on users from the who command so for each iteration of the passwd users you could loop over the list of logged on users testing (ha!) for a match. If you find a match or not then you do as required. That will require a flag variable, set to not found (found=0) before entering the logged on users loop and set to found (found=1) in the loop when you do find a match. After the logged on users loop, test the found flag ...

mmatt 07-18-2009 04:11 PM

I'll retract my statement about nested for loops being inefficient, using time they were ~5x quicker than the call to grep...

colucix 07-18-2009 04:18 PM

Basically there are two forms of if/then tests: 1) test if an expression is true; 2) test if the exit status of a command is 0 (success). The syntax of the first form is:
Code:

if [ expression ]
then
  command
  command
  ...
fi

An expression can be a string comparison, an arithmetic comparison or a file test (see man test to see all the possibilities, but take in mind that you don't need to use the test command, since the square brackets already perform a test).

The syntax of the second form is:
Code:

if command
then
  command
  command
  ...
fi

Here the command after "if" is actually executed (whatever it be) and its exit status is evaluated: if the command had success then the if/then body is executed, if the command failed then the if/then body is ignored.

In your case, you have to think which command tells you if a particular user is logged in, then just put it after "if". For example:
Code:

if who | grep $user > /dev/null
then
  echo user $user is logged in
else
  echo user $user is not logged in
fi

Is up to you to know what a pipe means and why I used redirection to /dev/null.

For more examples about the if/then usage, you can see the Bash Guide for Beginners or any of the guides linked above.

mmatt 07-18-2009 05:39 PM

A much more thorough explanation colucix :). I'll just reiterate that grep -w $user would be better to avoid matching, for example, "daniel" when the $user variable is "dan".

catkin 07-19-2009 02:21 AM

Quote:

Originally Posted by mmatt (Post 3612086)
I'll retract my statement about nested for loops being inefficient, using time they were ~5x quicker than the call to grep...

Shell parameter expansion is usually a lot quicker for string manipulation than piping through (sometimes multiple) sed, awk etc. "Usually" because shell parameter expansion is gruesomely slow with big (say > 1 kB) strings. All of which is only significant when performance is an issue :)

mmatt 07-19-2009 05:05 AM

catkin you're right of course - no point spending extra minutes coding to save milliseconds at runtime... :)

chrism01 07-19-2009 07:03 PM

In general, I'd strongly advise the OP to bookmark and read(!) the Beginners & Advanced Bash guides referred to previously.
They are well written and have loads of examples.
You just need to read & write shell scripts, there's no substitute for experimentation here.
I will point out that using the line

set -xv

as the 2nd line of a script shows you exactly what its doing - think debug mode.

PAvandal 07-20-2009 09:31 PM

Well, somehow, it clicked!

My very, very limited knowledge of linux, combined with the bash beginners guide (thanks colucix!), helped me come up with a script that may not be the most efficient, but it works!

Code:

#!/bin/bash
users=`cat /etc/passwd | grep -v nologin | grep -v halt | grep -v shutdown | grep -v news | grep -v sync | grep -v vboxadd | cut -d: -f1`
logged=`last | grep -w still | grep -v pts | cut -d" " -f1`
homedir=`cat /etc/passwd | grep -w $logged | grep -v nologin | cut -d: -f6`
last=`last | grep -w still | grep -v pts | cut -c40-55`
list=`ls -l $homedir`
notlog=`last | grep -v still | grep -v pts | cut -d" " -f1 | sort | uniq | grep -v $logged`
echo $logged is logged in, and logged in at $last
for files in $list
do
        if [ -f $files ]     
        then echo $files is a file in their home directory.
        fi
done
echo $notlog are not logged in.

I'm so surprised and happy that I figured this out. Thanks everyone for your help, sincerely. I'm pretty confident that I can handle script#2 now.

I'm sure I'll be back for more help in the future!


All times are GMT -5. The time now is 08:30 AM.