1

Is there some reason why this Go program says neither that a file exists nor doesn't exist? Presumably it's one or the other?

package main

import (
    "fmt"
    "log"
    "os"
    "path/filepath"
)

func main() {

    for _, fn := range os.Args[1:] {
        src, _ := filepath.Abs(fn)
        fmt.Println(fn)
        fmt.Println(src)
        if _, e := os.Stat(src); os.IsExist(e) {
            log.Fatalf("Does exist: %s", src)
        }
        if _, e := os.Stat(src); os.IsNotExist(e) {
            log.Fatalf("Does not exist: %s", src)
        }
    }
}

3 Answers3

4

The os.IsExist and os.IsNotExist functions do not test opposite conditions, even though the names seem to imply that they do.

The function os.IsExist returns true when an operation fails because a file already exists. The function os.IsNotExist returns true when the operation fails because the file does not exist.

The function os.Stat always returns an error with os.IsExist(err) == false. The os.Stat function never fails because the file exists.

The function os.OpenFile with O_CREAT always returns an error os.IsNotExist(err) == false. Because the purpose of os.OpenFile with O_CREAT is to create a file, it is never an error for the file to be missing.

Simon Fox
  • 5,995
  • 1
  • 18
  • 22
2

Some functions fail if a file exists. The error returned by such a system call would satisfy os.IsExist(). One such system call is os.OpenFile() with flags O_CREAT and O_EXCL. Other functions fail if a file does not exist, like os.OpenFile without the O_CREAT flag. The error returned by such a system call would satisfy os.IsNotExist(). The nil error satisfies neither os.IsExist() and os.IsNotExist() as it is not a failure condition.

In your example, the os.Stat() function could fail if the file you try to stat does not exist. It could also fail if the file existed, but not for the reason of the file existing. Therefore, os.IsExist(e) will always yield false for an error produced by the os.Stat() function.

fuz
  • 88,405
  • 25
  • 200
  • 352
  • So, you're saying that `os.IsExist()` can return false for a file that exists? –  Sep 19 '14 at 18:02
  • @Ana Yes. `os.IsExist()` classifies an *error*. If the cause of an error `e` was the existance of a file, `os.IsExist(e)` is true. The `nil` error is not a proper error, as it indicates success and thus has no cause. – fuz Sep 19 '14 at 18:29
1

Best way to check if file exists (where src = path to file):

if _, err := os.Stat(src); err == nil || os.IsExist(err) {
    // your code here if file exists
}
AlSan
  • 383
  • 5
  • 9