lack of understanding > annoying error

I'm working on a script I wrote called backup.sh
when I run it like this:

. ./backup.sh

I get this error:

ksh: ./backup.sh[124]: no closing quote

when I run it this way:

backup.sh

I get this error:

backup.sh: 28: Syntax error: end of file unexpected (expecting "fi")

I looked through the code over and over (the entire script) and can't find any mismatching quotes or badly nested if statements. I don't have a strong enough understanding to know why one way is better or worse, and why either of them should be handled differently by the shell (I'm guessing they're being handled differently, otherwise they wouldn't have different output, right?)

Any help would be greatly appreciated. In-case this requires a look at the code:

#!/bin/sh

toBackUpDir="./tmp" #DIRECTORY TO BE BACKED UP
toBackUp="$toBackUpDir/*" #PATH TO BE BACKED UP
landingDir="./download/" #PATH FOR *.TGZ BACKUP TO BE STORED
sql_bDir="./sql_backups/"

#ERROR CHECK, DOES SPECIFIED LANDING DIRECTORY EXIST; ANY OLD BACKUPS?
echo "Checking for specified landing directory: $landingDir"

if [ -d $landingDir ]
then
    echo "Directory $landingDir is present and ready to receive backup."

    echo "Checking that $landingDir does not contain old backup files."
    tarCheck=`ls $landingDir | grep -i *tar*` #CHECKS IF ANY TAR IS SITTING IN DESTINATION FOLDER
    echo "The variable \$tarCheck returns:" $tarCheck #TEST OF VARIABLE

        # ERROR CHECK, ANY PREVIOUS BACKUPS STILL HERE?
        if [ -z $tarCheck ]
        then
            echo "Continuing backup sequence, as there are no old tars in the backup directory $landingDir"
            work="STARTING"
            echo "BEFORE NESTED ELSE"
        else
            echo "I am not ready to backup, first download and delete the above mentioned contents of the $landingDir landing directory." 
            work="NOT starting"
            echo "AFTER NESTED ELSE"
        fi #ENDIF FOR ERROR CHECKING
    echo "AFTER NESTED IF"
else
    echo "Directory $landingDir does not exist, creating it now"
    work="STARTING"
    mkdir $landingDir
fi #ENDIF LANDING DIR. CHECK


# MAIN MODULE: PARAMETERS, ERROR CHECK, TAR, GZIP
if [ $work = "STARTING" ]
then
        #OLD WAY: #fileName=`date | sed -n s/ /_/g p | sed -n s/^/Backup_/p | sed -n s/$/\.tgz/p |  sed -n s/^
/$landingDir/p`  #NAME OF BACKUP FILE
        fileName=`date | sed -n s/ /_/g p`
        fileName=${landingDir}Backup_${fileName}.tgz #NEW WAY #NAME OF BACKUP FILE

        #ERROR CHECK, DOES LOCATION TO BE BACKED UP EXIST?
        echo "The variable \$toBackUpDir (directory of files to be backed up) is: $toBackUpDir"
        echo "Making sure above said target exists: $toBackUpDir"

                if [ -d $toBackUpDir ]
                then
                        echo "Directory $toBackUpDir does indeed exist and is present for backing up."
    
        #CONTINUE PROGRAM

            echo "The variable \$fileName will be:" $fileName
    
        #START SQL BACKUP + TGZ 
            #MYSQL LANDING DIR. CHECK
            echo "Checking if sql backup landing directory exists: $sql_bDir"
            if [ -d $sql_bDir ]
            then
                echo "Database backup directory exists"
            else
                echo "Database backup directory does not exist, creating it"
                mkdir $sql_bDir
            fi #ENDIF SQL DIR. CHECK

            # MYSQL BACKUP
                   sql_bName=`date | sed -n s/ /_/g p | sed -n s/^/SqlBackup_`
            echo "The variable \$sql_bName will be $sql_bName" #TEST OF SQL NAME VARIABLE
            #mysqldump -uxxxxxx -pxxxxxx --opt information_schema > /$sql_bDir/$sql_bName.tgz

            # MYSQL CLEAN-UP < 10 FILES
            # CODE TO CLEAN UP OLDEST OF LISTING (ls -la)
            # THAT AMOUNTS TO GREATER THAN 10 ITEMS

            echo "Below are the files placed in final back up:" #EXPLANATION FOR USER
            tar zcvf "$fileName" $toBackUp #CREATE TGZ
    
            #DECLARE BACKUP FINISHED
            echo " " #VISUAL PADDING
            echo "Final back-up ready for download in, including \"information_schema\" database: $landingDir"

            else
            echo "ERROR:"
            echo "    Directory $toBackUpDir does not exist."
            echo "    Make sure my starting parameters are properly set."
            echo "Backup sequence ended early."
        fi #ENDIF BACKUP DIR. CHECK

fi #ENDIF FOR MAIN MODULE
                if [ -d $toBackUpDir ]
                then
                        echo "Directory $toBackUpDir does indeed exist and is present for backing up."
#<- Insert missing fi here    
        #CONTINUE PROGRAM

That if statement is ended at the bottom of the script (the "fi" can be found in the third to last line)

The else statement that forms the if you're looking at is at the 8th to last line

Can't find any missing " or ` but the line:

if [ -z $tarCheck ]

needs speech marks around the $tarCheck otherwise when it is empty the test will fail.

Not so critical but might help as the strings going into work have spaces in them I would put speech marks around $work in the line:

if [ $work = "STARTING" ]

The header of the script says /bin/sh and then you test it with ksh ./backup.sh, sh and ksh are of course different shells that treat some items differently.

What does running:

$ sh -n ./backup sh 

report?

Have you check this line?
>
#OLD WAY: #fileName=`date | sed -n s/ //g p | sed -n s/^/Backup/p | sed -n s/$/\.tgz/p | sed -n s/^/$landingDir/p` #NAME OF BACKUP FILE
>
Though you add comment at front of this line. You see that the editor wrap your text
down. However, you should check whether it is a consequent or separate statement.
The better way is add another comment to the second line.

In other hand, you can try and do debuging.
Just put comment to all the inner IF cause and put echo statement to verify that the if cause has not conflict. You can put echo command to show the flow and the assign value of each variable. Then you just remove the comment line by line and run for test.
You will then find the invalid statement.

Thanks for all your replies!

the script previously worked fine before this (I tested it in both cases), but for the sake of being thorough (and I trust most people's opinions over mine in this case) I've stuck the quotes in.

ahh, my newbie mistake - i forgot that . / would be in my shell which happens to be ksh ! didn't make the connection. thanks!

the above has the same result as just typing backup.sh into the terminal (i didn't know about -n option, noexec according to man, thanks!).

which, with all the above changes, is now:

./backup.sh: 28: Syntax error: end of file unexpected (expecting "fi")

The line you're referring to is indeed only one line, without any breaks (though I know what you're saying, their isn't anywhere I can stick a second comment).

I actually did try doing this debugging - but not through out the entire script. Now its done and this is the code I used for the output I get:

CODE USED:

...
                         echo "BEFORE NESTED ELSE"#DEBUG
                 else
                         echo "I am not ready to backup, first download and delete the above mentioned contents of the $landingDir landing direct
ory."
                         work="NOT starting"
                         echo "AFTER NESTED ELSE"#DEBUG
                 fi #ENDIF FOR ERROR CHECKING
         echo "AFTER NESTED IF" #DEBUG
 else
         echo "Directory $landingDir does not exist, creating it now"
         work="STARTING"
         mkdir $landingDir
 fi #ENDIF LANDING DIR. CHECK
 
 echo "PAST LANDING DIR. CHECK" #DEBUG
 
 # MAIN MODULE: PARAMETERS, ERROR CHECK, TAR, GZIP
 if [ "$work" = "STARTING" ]
 then
         echo "INSIDE INITIAL IF - STARTER" #DEBUG

OUPUT REC'V:

...
Continuing backup sequence, as there are no old tars in the backup directory ./download/
BEFORE NESTED ELSE#DEBUG
AFTER NESTED IF
PAST LANDING DIR. CHECK
backup.sh: 29: Syntax error: end of file unexpected (expecting "fi")

Moved down a line to 29 because of the debugger echos i've inserted? not very helpful, as far as I can tell.

Incase anyone else sees this (and no it doesn't solve the syntax error):

I hadn't added an "else" to the most outer layer "if" statement (labeled "# MAIN MODULE: PARAMETERS, ERROR CHECK, TAR, GZIP") so I moved one of the lines a few spots downward to sit in-between the last two "fi" statements, like so (bottom of script):

                fi #ENDIF BACKUP DIR. CHECK
         else
                echo "Backup sequence ended early."
fi #ENDIF FOR MAIN MODULE

Your problem is so interesting.
I copy your script and try to execute on my server. Unfortunatly, I am using Solaris 9.5.
So, except the tar option that may different between Solaris 9 and 10. ( I put comment on this statement). I run your script but I do not find any error as same as you are.

So, please try "truss" command to trace echo on the step that your script is running.
Fore example :
$ truss sh ./backup.sh

Thanks for your time, really! I ran:

truss -o trussOut sh./backup.sh

I'm not completely sure how this truss command works, aside from its man page's explanation (and the output it produced is 241 lines of stuff that looks over my head) - I would paste it, but previewing my post with a paste of it is showing that it doesn't get its only scrolly frame and instead is HUGE. So i'm attaching it. Let me know if ANY one comes up with anything.

maybe someone can tell me that the way i'm going about my end product is ridiculous and I should be doing it differently?

The another try.
Please try to use
if [ $work -eq "STARTING" ]
instead of
if [ $work = "STARTING" ]

Why don't you use:

test [ -d $toBackUpDir ]

instead of

if [ -d $toBackUpDir ]

the option -d <file> should use with test command,isn't it?

Your if statement may not correct.
Since the -f <file>, -z <file> should use in test statement instead of if cause.

I've tried this before and I get and error explaining that "eq" is for mathematical tests, after looking it up I found that indeed its = that's used for strings.

Ahhh - just the kind of advice I was looking for! (I'm still quite new to UNIX).

I tried your suggestion with test, but get this (with and without quotes):

backup.sh: 131: Syntax error: EOF in backquote substitution

I now am using (according to the wikipedia outline of test):

if test -d "$toBackUpDir"

but alas, the above gives the same exact error I've been getting:

backup.sh: 29: Syntax error: end of file unexpected (expecting "fi")

incase my code has changed drastically since my initial post, I've attached an updated copy.

Oop! I give you a wrong syntax.
please use test within if cause fore example:
#!/bin/sh
cfile="./download"
if test -d $cfile
then
echo "$cfile is exist "
ls -l $cfile
else
echo "can not find $cfile"
fi

this script has been tested. if you can use it on your site. Then you can apply it to your script.

please try this:
tarCheck=`ls $landingDir/*tar*`
instead of belowing.

tarCheck=\`ls $landingDir | grep -i \*tar*\`

You are correct about "if [ "$work" = "STARTING" ]".

  1. I put
    work=""
    after your sql_Dir=... statement

  2. I modify the statement
    echo "PAST LANDING DIR. CHECK with work = $work in the $landingDir copy to $toBackUpDir"
    to trace on variable's value

  3. I change your if cause script from if [ -<option> <argument>] to if test -<option> <argument>
    and execute the script.
    I get this.

_______________________________________________________
backup.sh is a shell script designed to backup pre- |
specified files to a pre-specified file path. For |
details see the parameters. - Jonathan Zacsh 5/20/09 |
______________________________________________________|
Script Started: Wed May 20 12:54:52 ICT 2009
---------------

Checking for specified landing directory: ./download/
Directory ./download/ is present and ready to receive backup.
Checking that ./download/ does not contain old backup files.
The variable $tarCheck returns: ./download//super_backup.tar
I am not ready to backup, first download and delete the above mentioned contents of the ./download/ landing directory.
AFTER NESTED ELSE#DEBUG
AFTER NESTED IF
PAST LANDING DIR. CHECK with work = NOT starting in the ./download/ copy to ./tmp
AFTER OUTER-LAYER IF-STATEMENT
Backup sequence ended early.

---------------
Script Ended: Wed May 20 12:54:52 ICT 2009
_______________________________________________________
|_____________________________________________________|

So it means if you can get this you can continue to fine tune your script.
I hope you will get it.
Note: super_backup.tar is existing in my sudirectory download .

haha, I was using such a complicated approach! thanks

-I did part 1 (pre-setting the variable $work)
-I did part 2 (actually, clarified a few of my "debugger" statements to be more helpful)
-I did part 3 - but, did you only change a few of the if statements to if test? or did you change every if statement in the script to if test? I changed everything to if test

and STILL I'm getting the same exact error:

Checking for specified landing directory: ./download/
Directory ./download/ is present and ready to receive backup.
Checking that ./download/ does not contain old backup files.
The variable $tarCheck returns: ./download/tar
I am not ready to backup, first download and delete the above mentioned contents of the ./download/ landing directory.
AFTER NESTED ELSE, WORK HAS BEEN SET TO NOT starting
AFTER NESTED IF, WORK HAS BEEN SET TO: NOT starting and no previous backups exist
PAST LANDING DIR. CHECK with work = NOT starting the ./tmp copy to ./download/
backup.sh: 29: Syntax error: end of file unexpected (expecting "fi")

I've attached my copy of the script. I figure it'll be easier if you do:
diff yourCopy myCopy
and let me know what's different? or post your version up and I'll do it.. because I'm thinking maybe I misunderstood one of these many past pieces of advice in this thread, and i'm not on the same page? or maybe you could run my script, and if it works than I'll know its my system that's different (though, i very highly doubt that will be the case)...? shooting for anything here. thanks again

Hi! I change the if cause only that it should use the test command.
I remove some of your comment lines to make it easy to sweep my eyes on it.
I attach the test file to let you take a look on it.

Hope this can help.

OH no! you called it from the beginning but I thought the vi editor which showed line numbers (and it really only did show ONE line number for that entire thing) was enough proof!

Man, I'm sorry tom_cmu. Well atleast I learned how to clean up my code, and not to really rely on the silly logical expectations I have of the software I use. (I only really noticed this when I downloaded my own copy to my xp machine and viewed it with Notepad++, the syntax highlighting is what made it so obvious something was wrong with that line)

removed this, and everything was fine:

  #OLD WAY: #fileName=`date | sed -n s/ /_/g p | sed -n s/^/Backup_/p | sed -n s/$/\.tgz/p |  sed -n s/^/$landingDir/p`  #NAME OF BACKUP FILE

Thanks again for all the help - this was some seriously awesome community support here, thank you!

ps. is there some way to mark this thread as solved?

This bit is two lines, not one. The second line is therefore not commented out.

       #OLD WAY: #fileName=`date | sed -n s/ /_/g p | sed -n s/^/Backup_/p | sed -n s/$/\.tgz/p |  sed -n s/^
/$landingDir/p`  #NAME OF BACKUP FILE