Linux – Redhat Shell Script If Statement fails with odd syntax error

bashlinuxscriptingshell

Redhat 5.3 Enterprise

The following Shell script is used to check and see if a backup directry is named "ll_backup", then changes it to equal the content of a file RESULT.VAR. The result.var file is copied for log purposes to another directory. I had this working in a test enviorenment but in production it throughs a weird error that I can't for the life of me figure out!

SCRIPT:

#!/bin/bash
#!/bin/cat
# Restores original directory name for next LogLogic Update
#TCJ 6/1/09
declare RESULT
declare FILE
FILE=result.var
cd /home/nb-backup/backups/nb-st3000/ll_bkup_65.99.220.172/
if [ -d ll_bkup ]
 then
        cat result.var | while IFS=: read RESULT
        mv  "ll_bkup" "$RESULT"
        mv result.var /home/storegrid/scripts/results/result-`date +%y%m%d%s`.var
else
         exit 0
fi
exit 0

RESULT:

nb-script-restorellbackup.sh: line 14:
syntax error near unexpected token
else' nb-script-restorellbackup.sh:
line 14:
else'

Best Answer

There are a number of problems, ranging from minor to fatal (all of the fatal ones have to do with the "cat...while...read" line). Let me go through them in order:

  • As Dennis Williamson pointed out, the "#!/bin/cat" and "declare..." lines don't do anything.
  • You set FILE to result.var near the top, but then never use this variable. Assuming it's intended to allow you to change the filename in just one place, you should replace all other references to result.var with "$FILE"
  • The while statement needs a "do...done" - or rather, it would if you actually needed the while statement in the first place. Since you're only reading one RESULT from the file, you don't need a loop.
  • Since the "read RESULT" is part of a pipeline, it runs in a subshell, and the value of RESULT it sets is lost when that subshell exits. You could fix this by using something like 'read RESULT <"$FILE"'.
  • What's the "IFS=:" bit there for? It sets the internal field separator to ":" for the duration of the read command, but since you're only reading one field (RESULT), the only thing it does is to trim leading or trailing colons from what's read from result.var. If you meant to ignore everything after a colon (i.e. only use the first colon-delimited field from result.var), you should use "IFS=: read RESULT IGNOREDJUNK" instead.
  • Unless you're actually trying to trim/parse the contents of result.var, or need to use it several times, you don't need to read it into a variable at all; just use 'mv "ll_bkup" "$(cat "$FILE")"'. But I claim you want to use it again (see below).
  • The script is rather fragile in the sense that it doesn't check to make sure result.var exists (and since the script moves that file, if run twice in a row it's guaranteed to fail the second time); similarly, it doesn't check if "$RESULT" already exists before trying to rename ll_bkup to it, leading to potentially unpredictable results.
  • Speaking of which, your description says result.var gets copied, but the actual code moves it. Which is the intended behavior?
  • Finally, the "else... exit 0" section does nothing that the "exit 0" at the end isn't about to do anyway.

Gripe, gripe, gripe... anyway, here's my proposed rewrite:

#!/bin/bash
# Restores original directory name for next LogLogic Update
#TCJ 6/1/09
FILE=result.var
cd /home/nb-backup/backups/nb-st3000/ll_bkup_65.99.220.172/
if [ -d ll_bkup -a -f "$FILE" ]; then
    read RESULT <"$FILE"
    if [ ! -e "$RESULT" ]; then
        mv  "ll_bkup" "$RESULT"
        mv "$FILE" /home/storegrid/scripts/results/result-`date +%y%m%d%s`.var
    fi
fi
exit 0
Related Topic