517 votes

Comment vérifier si un fichier existe dans Go ?

La bibliothèque standard de Go ne dispose pas d'une fonction destinée uniquement à vérifier si un fichier existe ou non (comme la fonction de Python os.path.exists ). Quel est le idiomatique manière de le faire ?

2 votes

Je ne comprends pas vraiment. Au même moment vous dites qu'il n'y a pas de fonction standard et vous écrivez une réponse avec la fonction standard. Qu'est-ce qui m'échappe ? La question ne devrait-elle pas au moins être corrigée ?

0 votes

@dystroy - j'ai corrigé la question.

12 votes

Il vaut mieux éviter de demander l'existence de dossiers. En raison de la nature osée de la réponse, l'information obtenue ne dit en fait rien d'utile au-dessus du fichier qui existait au moment de la demande - mais qui n'existe peut-être plus. La méthode recommandée est d'ouvrir simplement un fichier et de vérifier si cela échoue ou non.

806voto

Sridhar Ratnakumar Points 12390

Pour vérifier si un fichier n'existe pas, l'équivalent de Python if not os.path.exists(filename) :

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

Pour vérifier si un fichier existe, l'équivalent de Python if os.path.exists(filename) :

Modifié : selon les commentaires récents

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

} else if errors.Is(err, os.ErrNotExist) {
  // path/to/whatever does *not* exist

} else {
  // Schrodinger: file may or may not exist. See err for details.

  // Therefore, do *NOT* use !os.IsNotExist(err) to test for file existence

}

3 votes

Parfois, il renvoie ENOTDIR au lieu de NOTEXIST par exemple, si /etc/bashrc existent, le /etc/bashrc/foobar retournera ENOTDIR

49 votes

Le deuxième extrait est plus subtilement faux ; la condition devrait être !os.IsNotExist(err) . Il est possible que le fichier existe mais os.Stat échoue pour d'autres raisons (par exemple, autorisation, disque défaillant). Utilisation de err == nil car la condition catégorise incorrectement de tels échecs comme "le fichier n'existe pas".

9 votes

Pour vérifier si un fichier existe, c'est faux : err est nul si le fichier existe

142voto

OscarRyz Points 82553

Réponse par Caleb Spare publié dans gonuts liste de diffusion.

[...] Il n'est en fait pas très souvent nécessaire et [...] en utilisant os.Stat est assez facile pour les cas où elle est nécessaire.

[...] Par exemple : si vous allez ouvrir le fichier, il n'y a aucune raison de vérifier d'abord s'il existe. Le fichier pourrait disparaître entre la vérification et l'ouverture, et de toute façon, vous devrez vérifier l'existence du fichier. os.Open de l'erreur. Il suffit donc d'appeler os.IsNotExist(err) après avoir essayé d'ouvrir le fichier, et de gérer sa non-existence à cet endroit (si cela nécessite un traitement spécial).

[...] Vous n'avez pas besoin de vérifier l'existence des chemins (et vous ne devriez pas).

  • os.MkdirAll fonctionne que les chemins existent déjà ou non. (Vous devez également vérifier l'erreur de cet appel).

  • Au lieu d'utiliser os.Create vous devez utiliser os.OpenFile(path, os.O_RDWR|os.O_CREATE|os.O_EXCL, 0666) . De cette façon, vous obtiendrez une erreur si le fichier existe déjà. De plus, il n'y a pas de condition de course avec quelque chose d'autre qui crée le fichier, contrairement à votre version qui vérifie l'existence au préalable.

Tiré de : https://groups.google.com/forum/#!msg/golang-nuts/Ayx-BMNdMFo/4rL8FFHr8v4J

52voto

Vous devez utiliser le os.Stat() y os.IsNotExist() comme dans l'exemple suivant :

func Exists(name string) (bool, error) {
    _, err := os.Stat(name)
    if err == nil {
        return true, nil
    }
    if errors.Is(err, os.ErrNotExist) {
        return false, nil
    }
    return false, err
}

edit1 : correction du problème du retour de true dans certaines circonstances.
edit2 : changement d'utilisation de errors.Is() à partir de os.IsNotExist(), qui, selon beaucoup, est une erreur. meilleures pratiques y aquí

15 votes

Attention : comme stackoverflow.com/a/22467409/712014 a souligné, ce code retourne vrai, même si le fichier n'existe pas, par exemple lorsque Stat() retourne une permission refusée.

48voto

Dave Yarwood Points 1661

La première chose à considérer est qu'il est rare que vous souhaitiez seulement vérifier si un fichier existe ou non. Dans la plupart des situations, vous essayez de faire quelque chose avec le fichier s'il existe. Dans Go, chaque fois que vous essayez d'effectuer une opération sur un fichier qui n'existe pas, le résultat devrait être une erreur spécifique ( os.ErrNotExist ) et la meilleure chose à faire est de vérifier si le retour err (par exemple, lors de l'appel d'une fonction telle que os.OpenFile(...) ) est os.ErrNotExist .

La méthode recommandée pour ce faire utilisé pour être :

file, err := os.OpenFile(...)
if os.IsNotExist(err) {
    // handle the case where the file doesn't exist
}

Cependant, depuis l'ajout de errors.Is dans Go 1.13 (sortie fin 2019), la nouvelle recommandation est d'utiliser errors.Is :

file, err := os.OpenFile(...)
if errors.Is(err, os.ErrNotExist) {
    // handle the case where the file doesn't exist
}

Il est généralement préférable d'éviter d'utiliser os.Stat pour vérifier l'existence d'un fichier avant d'essayer d'en faire quelque chose, car il sera toujours possible que le fichier soit renommé, supprimé, etc. dans la fenêtre de temps avant que vous n'en fassiez quelque chose.

Cependant, si vous êtes d'accord avec cette réserve et que vous voulez vraiment, vraiment juste vérifier si un fichier existe sans ensuite faire quelque chose d'utile avec lui (à titre d'exemple artificiel, disons que vous écrivez un outil CLI inutile qui vous dit si oui ou non un fichier existe et ensuite se termine ¯\_(ツ)_/¯ ), la méthode recommandée serait alors la suivante :

if _, err := os.Stat(filename); errors.Is(err, os.ErrNotExist) {
    // file does not exist
} else {
    // file exists
}

29voto

ZuBsPaCe Points 490

Ce que les autres réponses ont omis, c'est que le chemin donné à la fonction pourrait en fait être un répertoire. La fonction suivante s'assure que le chemin est réellement un fichier.

func fileExists(filename string) bool {
    info, err := os.Stat(filename)
    if os.IsNotExist(err) {
        return false
    }
    return !info.IsDir()
}

Une autre chose à signaler : Ce code pourrait encore conduire à une situation de course, où un autre thread ou processus supprime ou crée le fichier spécifié, alors que la fonction fileExists est en cours d'exécution.

Si cela vous inquiète, utilisez un verrou dans vos threads, sérialisez l'accès à cette fonction ou utilisez un sémaphore inter-processus si plusieurs applications sont impliquées. Si d'autres applications sont impliquées, hors de votre contrôle, vous n'avez pas de chance, je suppose.

0 votes

Si d'autres applications sont concernées, vous voudrez peut-être conserver vos fichiers dans un dossier distinct. Si vous créez de nouveaux fichiers, O_EXCL est votre ami pour éviter les courses (si la plateforme que vous utilisez supporte ce drapeau).

0 votes

Ne pas utiliser cette cause info pourrait être nul lors de l'appel return !info.IsDir()

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X