LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   Help With Homework Assignment (https://www.linuxquestions.org/questions/programming-9/help-with-homework-assignment-4175496767/)

boygenuis 03-02-2014 02:11 PM

Help With Homework Assignment
 
I'm having some issue with a homework assignment on shell scripting. The instructor gave me this pseudo code:

Code:

BEGIN
    set FINDALL to false
    IF $1 equals -a THEN
        set FINDALL to TRUE
        dispose of $1
    END-IF
    FOR each Positional Parameter ($file) DO
        IF $file is a pathname THEN
            IF if $file is executable and not a directory THEN
                echo $file
            ELSE
                echo $file  is NOT Found
            END-IF
        ELSE
            set FOUND to false
            # Don't forget to handle the special cases of PATH
            FOR  P in PATH (: separated list) DO
                IF $P/$file is executable and not a directory THEN
                    set FOUND to true
                    echo $P/$file
                    IF FINDALL is FALSE THEN
                        BREAK FROMTHE for  LOOP
                    END-IF
                ELSE
                END-IF
                IF FOUND is FALSE THEN
                    echo $file is NOT FOUND
                END-IF
            END-FOR
        END-IF
    END-FOR
END

I can't quite get my code to work. Like, I'll run it and get no echo. I also fear I am not commenting well or formatting well for general readability. If someone has some time and wants to relive their college freshmen days, can you point me in a good direction? Thank you.

Code:

#! /bin/sh

#set a flag to check if you should search all for all occurances
#by default, you will only find the first occurance

FINDALL=FALSE
        case $1 in
          -a)
            FINDALL=TRUE
                #throw away this argument
            shift
            ;;
        esac
for file
        do
        #if $file is a pathname
        case $file in
        */*)
        #if $file is executable and not a directory       
                if [ -x "$file" ]
                        then
                        if [ !-d "$file" ]
                                then
                                echo "$file"
                else
                        echo "$file NOT FOUND"
                        fi
                fi
                ;;
        *)        #no / in the filename
                FOUND=FALSE
                ;;
        esac
#handle special cases of PATH
for P in `echo $PATH | sed -e 's/^:/.:/' -e 's/::/:.:/' -e 's/:$/:./' -e 's/:/ /g'`
        do                        #start the do loop through PATH       
        #test if $P/$file is a directory or executable
        case $file in
        *)
                if [ -f "$P/$file" ]
                        then
                        if [ !-d "$P/$file" ]
                                then
                                FOUND=TRUE
                                echo "$P/$file"
                        else [ FINDALL=FALSE ]
                        break
                        fi
                fi
                ;;
        esac
        done
        if [$FOUND=FALSE]
                then
                echo "$file NOT FOUND"
                fi
done


notKlaatu 03-02-2014 03:46 PM

I'm assuming the purpose of this script is to find whether or not the file issued as an argument actually exists or not..?

You're close, I think.

As a general rule, it's a good idea to "protect" your variables. So instead of writing things like

Code:

$P/$file
it is considered safer to write it:
Code:

${P}/${file}
And finally, I would say it's a good idea to insert "echo" statements A LOT when initially testing stuff. For me, these act a little like debugging statements, and it helps me know where exactly what is going on as the programme runs.

For instance, before entering an 'if' statement, precede it with a simple
Code:

echo "DEBUG: an if statement to test if file is exec or not"
or something like that. This way, you see what tests have passed and failed, and that ought to help you debug your own logic.

metaschima 03-02-2014 04:31 PM

Within the test command, the '=' and '==' are equivalent for bash. In fact, '=' is more compatible with sh.

You should certainly analyze the errors generated by the script. Also try using the 'bash -x' option to enter debug mode.
Also see:
http://www.cyberciti.biz/tips/debugg...ll-script.html

grail 03-02-2014 07:45 PM

As not mentioned earlier, please place code / data in [code][/code] tags so it is more readable and maintains your formatting.

notKlaatu 03-03-2014 12:14 AM

Quote:

Originally Posted by metaschima (Post 5127615)
Within the test command, the '=' and '==' are equivalent for bash. In fact, '=' is more compatible with sh.

You should certainly analyze the errors generated by the script. Also try using the 'bash -x' option to enter debug mode.
Also see:
http://www.cyberciti.biz/tips/debugg...ll-script.html

I've edited my post just so it does not contain incorrect information for others who read this.

Thanks for the info, metaschima.

catkin 03-03-2014 07:02 AM

There are two unmatched fis and $file never has a value assigned to it.

Here's the script with indentation
Code:

#! /bin/sh

#set a flag to check if you should search all for all occurances
#by default, you will only find the first occurance

FINDALL=FALSE
case $1 in
    -a)
        FINDALL=TRUE
        #throw away this argument
        shift
    ;;
esac
for file
do
    #if $file is a pathname
    case $file in
        */*)
            #if $file is executable and not a directory
            if [ -x "$file" ]
            then
                if [ !-d "$file" ]
                then
                echo "$file"
            else
                echo "$file NOT FOUND"
            fi
            fi    # <<  Unmatched fi
            ;;
        *) #no / in the filename
            FOUND=FALSE
            ;;
    esac
    #handle special cases of PATH
    for P in `echo $PATH | sed -e 's/^:/.:/' -e 's/::/:.:/' -e 's/:$/:./' -e 's/:/ /g'`
    do #start the do loop through PATH
        #test if $P/$file is a directory or executable
        case $file in
            *)
                if [ -f "$P/$file" ]
                then
                    if [ !-d "$P/$file" ]
                    then
                    FOUND=TRUE
                    echo "$P/$file"
                else [ FINDALL=FALSE ]
                    break
                fi
                fi    # <<  Unmatched fi
                ;;
        esac
    done
    if [$FOUND=FALSE]
    then
        echo "$file NOT FOUND"
    fi
done


boygenuis 03-03-2014 02:24 PM

Thank you, all, for your help. I've tried to make my edits based on your recommendations and here's what I've got so far. Also, because I forgot to put it earlier, the objective for this program is, "Write a shell script to locate executable files. This script takes a list of file names from the command line and determines which would be executed had these names been given as commands."

Code:

#! /bin/sh -xv

#Student: boygenuis
#Course: Shell Scripting
#Assignment: Locating Executable Files
#Date: 03 MAR 2014

#set a flag to check if you should search all for
#all occurrences. By default, you will only find
#the first occurrence

file="$1"
FOUND="$2"
 
$FINDALL = FALSE
        case $1 in
        -a)
                FINDALL = TRUE
                shift  #throw away this argument
                ;;
        esac
for file
        do
        #if $file is a pathname
        case $file in
        */*)
        #if $file is executable and not a
        #directory
                if [ -x "$file" -a ! -d "$file" ]
                        then
                        echo "$file"
                else
                        echo "$file NOT FOUND"
                fi
                ;;
#handle the special cases of PATH, start the DO loop
#through PATH, and test if $P/$file is a directory or
#executable
        *)
                for P in `echo $PATH | sed -e 's/^:/.:/' -e 's/::/:.:/' -e 's/:$/:./' -e 's/:/ /g'`
                do
                case $file in
                *)
                        if [ -f "$P/$file" -a ! -d "$P/$file" ]
                                then
                                FOUND = TRUE
                                        echo "$P/$file"
                        echo "DEBUG: Test if if [ FINDALL = FALSE ]"
                        if [ $FINDALL = FALSE ]
                                then
                                break
                                fi
                        fi
                        ;;
                esac
                done
                if [ $FOUND = FALSE ]
                        then
                        echo "$file NOT FOUND"
                fi
                ;;
        esac
done


notKlaatu 03-03-2014 04:13 PM

It appears to work for me, with a few slight changes:

Line 15

Code:

$FINDALL = FALSE
should read
Code:

FINDALL=FALSE
and Line 18
Code:

FINDALL = TRUE
should read
Code:

FINDALL=TRUE
Other wise it did seem to work insofar as I entered
Code:

boygenius.sh python
and got
Code:

/usr/bin/python
in return. Didn't really do any testing beyond that.

As grail points out though, you really should use this markup when pasting in code:
[code]
code goes here
[/code]

grail 03-03-2014 08:44 PM

It is forgivable to have not done so the first time, but to ignore the request and do it again is not. Please go back and edit both posts and place your code in code tags.

I for one will not read something that is not formatted and as was pointed out by catkin, this simple process would have led you to find easily fixable issues.

TB0ne 03-04-2014 09:39 AM

Regardless of the post formatting, the OP has shown adherence to the forum rules about posting homework, has shown effort of their own, and has been polite throughout. More posters should follow that example, in my opinion.

grail 03-04-2014 10:58 AM

And I am not chiding them for their good effort, but unfortunately with my old eyes the lack of contrast and formatting makes it difficult to assist :(

metaschima 03-04-2014 11:02 AM

Indent is also extremely useful in looking at code. If it's not in code tags, I tend to not look too closely at it.

PTrenholme 03-04-2014 01:54 PM

Re the post #8 by notKlaatu, one point made is that spaces are "tokenizers" in bash and Posex-compliant variants. (bash, itself, is not Posix-compliant.) Thus A = B is three "tokens," whilst A=B is one "token," and interpreted as an implicit let command.

The other point is that $ is a substitution command, and a command can't occur as the target of an assignment.

szboardstretcher 03-04-2014 02:00 PM

Thats a great explanation.

To add to that... the reason bash tokenizes them using spaces is a variable called IFS which defaults to " \t\n" easier read as "(space)(tab)(newline)"

TB0ne 03-04-2014 02:06 PM

Quote:

Originally Posted by grail (Post 5128766)
And I am not chiding them for their good effort, but unfortunately with my old eyes the lack of contrast and formatting makes it difficult to assist :(

Believe me...I agree with you; I don't wear bifocals for fun. :) But I did want to give credit to the OP, especially given the MANY homework requests we see that are barely intelligible and/or posted verbatim from a book, with no effort at all.


All times are GMT -5. The time now is 08:12 PM.