I have an if in my bash script that has to check if EITHER of the 2 files exists, if they don't exist it should echo match.

Code I have:

if [[ ! -f /etc/benchmarking/code ]] && [[ ! -f /etc/benchmarking/code.class ]]; then
 echo "match"

But this doesn't not seem to work for some reason.

I am 110% sure that these 2 files do not exist. I don't get any errors, it just doesn't enter the if.

I am new to bash scripting so I'm not sure what could be wrong.

  • I don't think any of the answers posted actually address the question. What happens when you try the tests individually? Do [[ ! -f /etc/.../... ]]; echo $? for each.
    – jw013
    Commented Sep 13, 2012 at 13:52
  • A warning: [[ -f xxx ]] returns true if xxx exists and is a regular file (or a symlink to a regular file). It will return false if it doesn't exist, or if it can't tell if it exists or not or if it exists but is not a regular file (directory, pipe, device, socket...) or if it's a symlink to a file that doesn't exist or it can't tell if it exists or not or is not a regular file... [[ -e $file ]] || [[ -L $file ]] is closer to a test for existence. ls -d -- "$file" > /dev/null 2>&1 is even closer. And as a rule, this kind of test leads to race conditions. Maybe there's another way. Commented Sep 14, 2012 at 20:37
  • I am way late to the party, but my bet is that the [ -f ] checks are just failing because they are under /etc which you likely do not have the permissions for, and you are running this script as non-root.
    – Brandon
    Commented Dec 29, 2021 at 0:51

4 Answers 4


If you want either then you want OR, not AND.

if [[ ! -f /etc/benchmarking/code ]] || [[ ! -f /etc/benchmarking/code.class ]]; then
 echo "match"
  • This will match if either or both files are missing.
  • Your code will only print match if both do not exist.

But, you said:

I am 110% sure that these 2 files do not exist. I don't get any errors, it just doesn't enter the if.

So your statement contradicts itself. At least one of those files must exist, if you are running that code.

If you want to see how your if statement is evaluating, run it with -x.

#!/bin/bash -x
if [[ ! -f /etc/benchmarking/code ]] && [[ ! -f /etc/benchmarking/code.class ]]; then
 echo "match"

Then you'll see the execution.

$ ./test.sh
+ [[ ! -f /etc/benchmarking/code ]]
+ [[ ! -f /etc/benchmarking/code.class ]]
+ echo match
  • I want it to echo "match" if neither file exists, if one does exist it doesnt print match. I will try it with -x Commented Sep 13, 2012 at 9:46
  • In that case your original code should be fine. And indeed it works for me.
    – bahamat
    Commented Sep 13, 2012 at 17:55

Shouldn't that be like this ? A is a file or B is a file, then blabla.

if [[ -f /etc/benchmarking/code ]] || [[ -f /etc/benchmarking/code.class ]]; 
  echo "match"

This may also work for what you are trying to do. Single brackets are not commonly used today with bash, but this is still an option. Using -o is effectively an "OR" operation, and ! negates the condition.

[ ! -f "$var" -o ! -f "$var.class" ] && echo "match"

Your code satisfies your requirements: it will print match provided that it can't find either file.

Therefore the reason match is not being printed is elsewhere. You should confirm that the code block is being reached, which you can do by surrounding it with a couple of debug message. For example, like this:

echo '@ About to enter if...fi block'
if [[ ! -f /etc/benchmarking/code ]] && [[ ! -f /etc/benchmarking/code.class ]]; then
 echo "match"
echo '@ Finished if...fi block'

My usual preference is for debugging messages to go to stderr so as to avoid interrupting the flow of data to stdout, but I have avoided that here because you said you were a beginner. Here is one example showing how you could write to stderr:

echo '@ About to enter if...fi block' >&2

You must log in to answer this question.

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