Syntax error near unexpected token 'fi'

Bash

Bash Problem Overview


I'm trying to write a script that removes all the .jpg's that end in an odd number. This is my code:

#!/bin/bash
echo "start\n"
for f in *.jpg
do
  fname=$(basename "$f")
  echo "fname is $fname\n"
  fname="${filename%.*}"
  echo "fname is $fname\n"
  if[$((fname %  2)) -eq 1 ] then
    echo "removing $fname\n"
    rm $f
  fi
done

When I run it it outputs start and then says "syntax error near unexpected token 'fi'"

When I had then on the line after if it said "syntax error near unexpected token 'then'"

How do i fix this?

Bash Solutions


Solution 1 - Bash

As well as having then on a new line, you also need a space before and after the [, which is a special symbol in BASH.

#!/bin/bash
echo "start\n"
for f in *.jpg
do
  fname=$(basename "$f")
  echo "fname is $fname\n"
  fname="${filename%.*}"
  echo "fname is $fname\n"
  if [ $((fname %  2)) -eq 1 ]
  then
    echo "removing $fname\n"
    rm "$f"
  fi
done

Solution 2 - Bash

Use Notepad ++ and use the option to Convert the file to UNIX format. That should solve this problem.

Solution 3 - Bash

"Then" is a command in bash, thus it needs a ";" or a newline before it.

#!/bin/bash
echo "start\n"
for f in *.jpg
do
  fname=$(basename "$f")
  echo "fname is $fname\n"
  fname="${filename%.*}"
  echo "fname is $fname\n"
  if [$[fname%2] -eq 1 ]
  then
    echo "removing $fname\n"
    rm $f
  fi
done

Solution 4 - Bash

The first problem with your script is that you have to put a space after the [.
Type type [ to see what is really happening. It should tell you that [ is an alias to test command, so [ ] in bash is not some special syntax for conditionals, it is just a command on its own. What you should prefer in bash is [[ ]]. This common pitfall is greatly explained here and here.

Another problem is that you didn't quote "$f" which might become a problem later. This is explained here

You can use arithmetic expressions in if, so you don't have to use [ ] or [[ ]] at all in some cases. More info here

Also there's no need to use \n in every echo, because echo places newlines by default. If you want TWO newlines to appear, then use echo -e 'start\n' or echo $'start\n' . This $'' syntax is explained here

To make it completely perfect you should place -- before arbitrary filenames, otherwise rm might treat it as a parameter if the file name starts with dashes. This is explained here.

So here's your script:

#!/bin/bash
echo "start"
for f in *.jpg
do
    fname="${f##*/}"
    echo "fname is $fname"
    if (( fname % 2 == 1 )); then
        echo "removing $fname"
        rm -- "$f"
    fi
done

Solution 5 - Bash

@sagar's answer solved my problem (Save file to UNIX format), please note that if you are using VSCode, you can select the file's end of line sequence (LF or CRLF) at the bottom right.

Also see this CRLF vs LF if you would like to understand the why. Common problem when you are working on different OS.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionCalvin KoderView Question on Stackoverflow
Solution 1 - BashjpriceView Answer on Stackoverflow
Solution 2 - BashSagarView Answer on Stackoverflow
Solution 3 - BashpeterhView Answer on Stackoverflow
Solution 4 - BashAleks-Daniel Jakimenko-A.View Answer on Stackoverflow
Solution 5 - BashcsamleongView Answer on Stackoverflow