4

I'm using Debian 10 (Buster) and am getting an error in a simple Bash script. All it does is check to see if one parameter is passed in, and if it's a file, just echo out the file:

#!/usr/bin/bash
if [ ( '$#' -eq 1 ) && ( -f "$1" ) ]; then
        echo "$1"
fi

exit 1

I get this error:

line 2: syntax error near unexpected token `'$#''
line 2: `if [ ( '$#' -eq 1 ) && ( -f "$1" ) ]; then'

I have tried every combination of quotes (", ', no quotes) around the $#, and I always get a variant of those error messages using the type of quotes I use. I can't figure out what it's looking for.

2
  • 11
    You may find shellcheck.net helpful Commented Sep 12, 2019 at 11:56
  • 5
    You don't actually need the $# -eq 1 test. The -f test would be false if there was no argument. Also, you shouldn't exit 1 if the script is successful.
    – Kusalananda
    Commented Sep 13, 2019 at 10:30

3 Answers 3

21

There are two issues here. First, the simple [ builtin can't contain &&. If you want to combine multiple conditions, you need multiple [:

if [ "$#" -eq 1 ] && [ -f "$1" ]; then

Second, you can't use single quotes around the $# since that needs to be expanded. Your version, with '$#' -eq 1 was comparing the string $# to the number 1.

The whole thing is much simpler if you use bash's [[ keyword instead:

if [[  "$#" -eq 1  &&  -f "$1"  ]]; then
0
11

[ is a command, so the problem is really the way you're trying to use multiple conditions. You want this:

if [ "$#" -eq 1 ] && [ -f "$1" ]; then
10

Despite the other answers explaining how to fix the script, I wondered what the error was technically about. I think the only valid syntax where bash allows a word in a command to be an unquoted and unescaped ( is when defining functions. So, bash saw ( and immediately thought it had to be a definition for a function named [, but then you followed with '$#' and bash was only expecting ), so that's why you got that syntax error. If it wasn't meant to be a function definition, then who knows what it was meant to be. Anything else after ( besides ) would have raised the same syntax error:

$ echo ( foo )
bash: syntax error near unexpected token `foo'

If you remove what follows ( that doesn't fit the syntax of a function definition, you get:

$ [ ( ) ( -f "$1" )

Which ends up defining the function [:

$ [
bash: -f: command not found
1
  • 5
    And the fact that it's an if-statement doesn't matter, you could still define a function within it. if [ () { echo hello; }; then [; [; fi prints hello twice.
    – ilkkachu
    Commented Sep 13, 2019 at 13:13

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .