Jak sprawdzić, czy plik lub katalog istnieje?

133

Chcę sprawdzić istnienie pliku ./conf/app.iniw moim kodzie Go, ale nie mogę znaleźć dobrego sposobu, aby to zrobić.

Wiem, że istnieje metoda File w Javie:, public boolean exists()która zwraca prawdę, jeśli plik lub katalog istnieje.

Ale jak można to zrobić w Go?

hardPass
źródło
7
Pamiętaj też, że w zależności od tego, jak zamierzasz wykorzystać te informacje, masz stan wyścigu. Wszystko, co możesz powiedzieć, to to, że jakiś czas temu plik istniał / nie istniał; zanim zaczniesz działać na teście, może być odwrotnie. Zwykle znacznie lepiej jest sprawdzić, wykonując dowolną operację, którą zamierzasz wykonać (np. Nie sprawdzaj przed otwarciem istniejącego lub utworzeniem nowego pliku, ale zrób f, err := os.Open(name)lub, f, err := os.OpenFile(name,os.O_CREATE|os.O_EXCL, mode)a następnie sprawdź os.IsNotExist(err)).
Dave C

Odpowiedzi:

195
// exists returns whether the given file or directory exists
func exists(path string) (bool, error) {
    _, err := os.Stat(path)
    if err == nil { return true, nil }
    if os.IsNotExist(err) { return false, nil }
    return false, err
}

Edytowano, aby dodać obsługę błędów.

Mostafa
źródło
4
Dla mnie wygląda to na „programowanie wyjątków”. Czy jest jakiś zasób, który uzasadnia ten rodzaj kodu jako oficjalny paradygmat #golang?
Olivier Amblet
22
@OlivierAmblet Nie ma tutaj wyjątku. Go używa panicdla rzeczywistego obiektu typu „wyjątek”. Możesz „złapać” telefonem do recover. Jawne zwracanie errjako drugiej wartości zwracanej jest niezwykle powszechną, idiomatyczną techniką Go. Zobacz: golang.org/doc/effective_go.html#errors
Chris Pfohl
13
rozwiązanie nie jest zbyt trudne, idź jest wyjątkowe
zhaozhi
1
Prawdą jest, że nie ma funkcji logicznej Exists, ale kod aplikacji może być prostszy, jeśli chcesz tylko sprawdzić istnienie pliku:if _, err := os.Stat("./conf/app.ini"); err == nil { /*exists*/ } else { /*not exists or some other error*/ }
Tobia
11
Dlaczego wszystko w tym języku jest takie skomplikowane?
Top Cat
125

Możesz użyć tego:

if _, err := os.Stat("./conf/app.ini"); err != nil {
    if os.IsNotExist(err) {
        // file does not exist
    } else {
        // other error
    }
}

Zobacz: http://golang.org/pkg/os/#IsNotExist

Denys Séguret
źródło
6
To jest lepsze niż zaakceptowana odpowiedź, ale czy klauzula else jest naprawdę konieczna?
Sergey Koulikov
10
@SergeyKoulikov Mogą wystąpić inne błędy, na przykład pozwolenie.
Denys Séguret
23

Bardziej do Twojej wiadomości, ponieważ rozejrzałem się przez kilka minut, myśląc, że moje pytanie będzie szybko odszukane.

Jak sprawdzić, czy ścieżka reprezentuje istniejący katalog w Go?

To była najpopularniejsza odpowiedź w moich wynikach wyszukiwania, ale tutaj i gdzie indziej rozwiązania zapewniają jedynie sprawdzenie istnienia. Aby sprawdzić, czy pathreprezentuje istniejący katalog, stwierdziłem, że mogę łatwo:

path := GetSomePath();
if stat, err := os.Stat(path); err == nil && stat.IsDir() {
    // path is a directory
}

Część mojego problemu polegała na tym, że spodziewałem się, że path/filepathpakiet będzie zawierał funkcję isDir ().

Edward Wagner
źródło
13

Prosty sposób sprawdzenia, czy plik istnieje, czy nie:

if _, err := os.Stat("/path/to/whatever"); os.IsNotExist(err) {
    // path/to/whatever does not exist
}

if _, err := os.Stat("/path/to/whatever"); err == nil {
    // path/to/whatever exists
}

Źródła:

Nikta Jn
źródło
Gdybym ci powiedział: „Prosty sposób na szybkie wzbogacenie się: wpłać pieniądze do banku. Weź pieniądze z banku”. można by pomyśleć, że mówiłem ci, że potrzebne są dwa kolejne kroki zamiast dwóch alternatywnych. Problem z tą odpowiedzią polega na tym, że czytelnicy mogą nie rozumieć, że sugerujesz dwa różne możliwe podejścia.
kfsone
0

Używam następującej funkcji, aby sprawdzić moje katalogi pod kątem błędów. Jest bardzo podobny do poprzednich odpowiedzi, ale myślę, że brak zagnieżdżenia ifs sprawia, że ​​kod jest bardziej przejrzysty. Używa go-homedirdo usuwania ~ze ścieżek katalogów i pkg/errorszwracania ładniejszych komunikatów o błędach, ale byłoby łatwo je usunąć, jeśli nie potrzebujesz ich funkcjonalności.

// validateDirectory expands a directory and checks that it exists
// it returns the full path to the directory on success
// validateDirectory("~/foo") -> ("/home/bbkane/foo", nil)
func validateDirectory(dir string) (string, error) {
    dirPath, err := homedir.Expand(dir)
    if err != nil {
        return "", errors.WithStack(err)
    }
    info, err := os.Stat(dirPath)
    if os.IsNotExist(err) {
        return "", errors.Wrapf(err, "Directory does not exist: %v\n", dirPath)
    }
    if err != nil {
        return "", errors.Wrapf(err, "Directory error: %v\n", dirPath)

    }
    if !info.IsDir() {
        return "", errors.Errorf("Directory is a file, not a directory: %#v\n", dirPath)
    }
    return dirPath, nil
}

Ponadto, aby powtórzyć komentarz @Dave C, jeśli powodem, dla którego sprawdzasz istnienie katalogu, jest zapisanie w nim pliku, zwykle lepiej po prostu spróbować po prostu spróbować otworzyć go później, aby rozwiązać problem z błędami:

// O_EXCL - used with O_CREATE, file must not exist
file, err := os.OpenFile(fileName, os.O_RDWR|os.O_CREATE|os.O_EXCL, 0666)
if err != nil {
    return errors.WithStack(err)
}
defer file.Close()
Ben
źródło
-3

Istnieje prosty sposób sprawdzenia, czy plik istnieje, czy nie:

if _, err := os.Stat("./conf/app.ini"); err != nil {
    if os.IsNotExist(err) {
        ..... //Shows error if file not exists
    } else {
       ..... // Shows success message like file is there
    }
}
Kabeer Shaikh
źródło
To jest duplikat odpowiedzi Denysa Ségureta.
StardustGogeta
Oprócz tego, że jest duplikatem, który musiał zostać naprawiony przez redaktora, jest to również błąd. Nigdy nie obsługuje przypadku, w którym istnieje plik.
kfsone