0

I am trying the below code. In that I am trying to check I get two files in the mentioned directory below, then I want to get completely out of the while loop! But if I have not received the files then it should keep iterating and waiting. But by using this below code I am getting error in the else part. The error is :

syntax error near unexpected token else

What should I do to fix it? Another question is how do I format my shell script in Visual Studio Code, I do not find any extension for it in VSC.

day_of_month=1
export filesdir=/dir1/dir2/dir3
local count=0
numFilesReceived=0
while true; do
        files=$(find $filesdir -name '*.txt.gz' -type f -mmin -1)
        if [ "$day_of_month" == "1" ]; then
            if [ -f "$files" ]; then
                count=$((count + 1))
                break
                if [ "$numFilesReceived" == "$count" ]; then
                    echo "All $count data received!"
                    break 3
                fi
            fi
            else
                echo "No data received yet!" 
            fi
            fi
             else
            rm $files
        fi
       done
4
  • one way to debug is to write after each fi a comment to mention opening if. e.g. fi # "$day_of_month" == "1" this way, you can check.
    – Archemar
    Jul 24 at 13:15
  • 3
    shellcheck.net is a free shell syntax checker, which you can either download or use online. Every error it flags has a wiki page giving more detail. Jul 24 at 14:47
  • 1
    Fix your indentation and you'll see where the keywords don't match up. Also, with that code, all shells I tried (+ shellcheck) complain about the token fi, not else. Namely, the one on line 19 if the first line of the code block (day_of_month=1) is line 1. Also, when posting code, you need to use code blocks to keep the code readable, see the first item in the editing help.
    – ilkkachu
    Jul 24 at 15:14
  • 1
    Please add a suitable shebang (#!/bin/bash) and then paste your script at shellcheck.net
    – Cyrus
    Jul 24 at 16:00
7

You are getting the error because you have unbalanced if/elses. The syntax of if/else in sh scripts is:

if condition 
then
    do something
else
    do something else
fi

Each if needs to be closed by a single fi. Next, you are storing all files in a single string variable:

files=$(find $filesdir -name '*.txt.gz' -type f -mmin -1)

This means that if your find command returns something like this:

$ find . -name '*.txt.gz' -type f
./file2.txt.gz
./file1.txt.gz

Then your variable's contents will be:

$ files=$(find . -name '*.txt.gz' -type f)
$ echo "$files"
./file2.txt.gz
./file1.txt.gz

But then you check for the existence of a single file with that name:

if [ -f "$files" ]; then

That will never be true since you don't have a file whose name is literally ./file2.txt.gz\n./file1.txt.gz and even if you do, that would also have been included in the results. In any case, you already know they are files and they exist since that is what the find command was doing, making this test doubly unnecessary.

You also have a lot of unnecessary variables, and you are setting day_of_month=1 and then using if [ "$day_of_month" == "1" ] which is pointless since that will always be true. Same for numFilesReceived and count. I don't understand what you want to do with those two, so I am guessing you want to set count to a non-0 value and then exit if the number of files matches that value. I also don't get what the point of the day_of_month is, I am guessing that you want to delete the files if this is the first day of the month. If so, you also need to check the curent date.

Here's a working version of my best guess for what I think you wanted:

#!/bin/bash

filesdir=/dir1/dir2/dir3
expectedFiles=2
dayToDelete=1

## Get the current day of the month
day_of_month=$(date '+%d')

while true; do
  ## If this is not the 1st day of the month, just delete the files
  ## and exit
  if [ "$day_of_month" != "1" ]; then
    find "$filesdir" -name '*.txt.gz' -type f -mmin -1 -delete
    exit
  ## If this is the first day of the month
  else
    ## You don't need the file names, only their number,
    ## so just print a dot so you don't need to worry about
    ## whitespace in the names
    fileCount=$(find "$filesdir" -name '*.txt.gz' -type f -mmin -1 -printf '.\n' | wc -l)
    if [[ "$fileCount" == "$expectedFiles" ]]; then
      echo "All $expectedFiles files received!"
      exit 
    else
      echo "No data received yet!"
      ## Wait for 5 seconds. No point in spamming, in fact you
      ## probably want to sleep for longer.
      sleep 5
    fi
  fi
done

I suspect this isn't really what you need, but I hope it can serve as a starting point. If you need more help, please ask a new question but give us the details of what the script is supposed to be doing so we can help you better.

3
  • thanks for your help. But in fileCount=$(find "$filesdir" -name '*.txt.gz' -type f -mmin -1 -printf '.\n' | wc -l) I dont want to check the number of files, I want to check if files are present so I can process them one by one in the further function in my script.
    – Aviator
    Jul 25 at 9:04
  • 1
    @Aviator yes, as I said I do not bt this is exactly what you need but since the logic of your script was unclear and you didn't explain what you need, all I could do is guess. I suggest you ask a new question where you explain what you are trying to achieve.
    – terdon
    Jul 25 at 11:35
  • Hi, I have asked a new question here : unix.stackexchange.com/questions/659861/…
    – Aviator
    Jul 25 at 13:49
3

You have 3 'if' statements, and 5 'fi' statements.

It's not fi...else, just else.

1
  • 3
    True, but that's the tip of the iceberg...
    – terdon
    Jul 24 at 13:38

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.