-2

I'm a beginner at shell scripting and I'm trying to run a simple script that uses the locate command to search for a file that the user enters. I'm trying to implement an if statement that returns true if any file with that name is found and prints it to the command line, however I believe I have an error in my if statement?

#!/usr/bin/bash
echo -n "Enter filename: "
read fileToFind

 if [ -z $fileToFind ]
 then
     echo "Error! No filename entered]
 else
    fileSearch=`locate -i $fileToFind

    if [ $fileSearch ]
    then
         echo $fileSearch
    else
         echo "No such file"
    fi
fi
Cyrus
  • 84,225
  • 14
  • 89
  • 153

2 Answers2

1

The primary problem is here:

if [ $fileSearch ]

When locate finds multiple matching files, this will cause an error because [ expects a single string while you're giving it multiple strings.

To prevent this, quote the variable:

if [ "$fileSearch" ]

You should always quote all variables, unless you know for a fact that you can't. Here's your script with complete quoting:

#!/usr/bin/bash
echo -n "Enter filename: "
read fileToFind

 if [ -z "$fileToFind" ]                 # 1
 then
     echo "Error! No filename entered"
 else
    fileSearch=`locate -i "$fileToFind"` # 2

    if [ "$fileSearch" ]                 # 3
    then
         echo "$fileSearch"              # 4
    else
         echo "No such file"
    fi
fi

#1 and #2 helps the search for files with spaces and special characters. #3 ensures you won't get errors for multiple files. #4 prevents multiple matches from being written out on a single line.

that other guy
  • 116,971
  • 11
  • 170
  • 194
  • Awesome! thanks for the help, this a common problem I've been running into while learning bash scripting is the proper use of quotes. – mmiller05 Apr 14 '17 at 21:56
1

As per @Cyrus's comment, I ran your code through http://shellcheck.net. Here's the result:

#!/usr/bin/bash
echo -n "Enter filename: "
read -r fileToFind

 if [ -z "$fileToFind" ]
 then
     echo "Error! No filename entered"
 else
    fileSearch=$(locate -i "$fileToFind")

    if [ "$fileSearch" ]
    then
         echo "$fileSearch"
    else
         echo "No such file"
    fi
fi

Pay attention to the syntax highlighting on this web page. Your code has a lot of red/magenta in it. That indicates that you haven't closed a quote someplace.

Now to your question:

I'm trying to implement an if statement that returns true if any file with that name is found and prints it to the command line...

Here's a style you may be interested in: An if statement will evaluate to true if the command it is executing returns a 0 exit code ( that is, returns successfully). In the case of locate ( based on my extensive research at https://linux.die.net/man/1/locate ), locate considers the invocation successful if a file is returned. locate will also output the result to the command line ( or stdout in linux parlance ). All that said, you could re-write your if statement like this:

    # other code omitted for focus/brevity
    if 
        ! locate -i "$fileToFind"
    then            
         echo "No such file"
    fi

In this case, I've negated the result with a !. So, if locate fails to find a file, your program will output "No such file". If locate does find the file, locate will just output it to stdout.

There is a slightly terser way of writing this code:

locate -i "$fileToFind" || echo "No such file"

In the statement above, you are asking bash to evaluate a logical OR || with short-circuit logic. bash will stop executing statements once the expression is true. So, in the case above, if locate is successful and finds a file, bash will not executed the right expression after the ||. This is a terse idiom that is fun to write, but it may be a little harder for others to understand. The if statement usually expresses your logic more clearly and its good to stick with if.

Mark
  • 4,249
  • 1
  • 18
  • 27
  • Thanks! this helped a lot! I wasn't aware that you could run the OR statement to do it. while learning I only stumbled upon the basic if/else – mmiller05 Apr 14 '17 at 21:54