web-dev-qa-db-fra.com

Vérifier de manière synchrone si le fichier / répertoire existe dans Node.js

Comment puis-je vérifier de manière synchrone, en utilisant node.js, si un fichier ou un répertoire existe?

1071
Ragnis

La réponse à cette question a changé au fil des ans. La réponse actuelle se trouve en haut, suivie des différentes réponses au fil des années dans l'ordre chronologique:

Réponse actuelle

Vous pouvez utiliser fs.existsSync() :

_const fs = require("fs"); // Or `import fs from "fs";` with ESM
if (fs.existsSync(path)) {
    // Do something
}
_

Il est obsolète depuis plusieurs années, mais ne l’est plus. De la docs:

Notez que fs.exists() est obsolète, mais fs.existsSync() ne l’est pas. (Le paramètre callback de fs.exists() accepte les paramètres incohérents avec les autres rappels Node.js. fs.existsSync() n'utilise pas de rappel.)

Vous avez spécifiquement demandé une vérification synchrone, mais si vous pouvez utiliser plutôt une vérification asynchrone (généralement préférable avec les E/S), utilisez fs.promises.access si vous utilisez des fonctions async ou fs.access (puisque exists est obsolète ) sinon:

Dans une fonction async:

_try {
    await fs.promises.access("somefile");
    // The check succeeded
} catch (error) {
    // The check failed
}
_

Ou avec un rappel:

_fs.access("somefile", error => {
    if (!error) {
        // The check succeeded
    } else {
        // The check failed
    }
});
_

Réponses historiques

Voici les réponses historiques par ordre chronologique:

  • Réponse originale de 2010
    (stat/statSync ou lstat/lstatSync)
  • Mise à jour septembre 2012
    (exists/existsSync)
  • Mise à jour en février 2015
    (Notant la désapprobation imminente de exists/existsSync, nous sommes donc probablement de retour à stat/statSync ou lstat/lstatSync)
  • Mise à jour de décembre 2015
    (Il y a aussi fs.access(path, fs.F_OK, function(){})/fs.accessSync(path, fs.F_OK), mais notez que si le fichier/répertoire n'existe pas, il s'agit d'une erreur; docs pour _fs.stat_ recommande d'utiliser _fs.access_ si vous devez vérifier l'existence sans ouverture)
  • Mise à jour en décembre 2016
    fs.exists() est toujours obsolète, mais fs.existsSync() n'est plus obsolète. Vous pouvez donc l'utiliser en toute sécurité maintenant.

Réponse originale de 2010:

Vous pouvez utiliser statSync ou lstatSync ( lien de la documentation ), ce qui vous donne un objet fs.Stats . En général, si une version synchrone d'une fonction est disponible, elle portera le même nom que la version asynchrone avec Sync à la fin. Donc, statSync est la version synchrone de stat; lstatSync est la version synchrone de lstat, etc.

lstatSync vous indique si quelque chose existe et, le cas échéant, s'il s'agit d'un fichier ou d'un répertoire (ou, dans certains systèmes de fichiers, d'un lien symbolique, d'un périphérique de bloc, d'un périphérique de caractère, etc.), par exemple. si vous avez besoin de savoir s'il existe et s'il s'agit d'un répertoire:

_var fs = require('fs');
try {
    // Query the entry
    stats = fs.lstatSync('/the/path');

    // Is it a directory?
    if (stats.isDirectory()) {
        // Yes it is
    }
}
catch (e) {
    // ...
}
_

... et de même, s'il s'agit d'un fichier, il existe isFile; s'il s'agit d'un périphérique en mode bloc, il y a isBlockDevice, etc., etc. Notez le _try/catch_; une erreur est générée si l'entrée n'existe pas du tout.

Si vous ne vous souciez pas de ce que l'entrée est ​​et que vous voulez seulement savoir si elle existe, vous pouvez utiliser path.existsSync (ou avec la dernière, _fs.existsSync_) as noté par l'utilisateur618408 :

_var path = require('path');
if (path.existsSync("/the/path")) { // or fs.existsSync
    // ...
}
_

Il ne nécessite pas de _try/catch_ mais ne vous donne aucune information sur la nature de la chose. _path.existsSync_ était obsolète depuis longtemps.


Note latérale: Vous avez expressément demandé comment vérifier de manière synchrone, j'ai donc utilisé les versions xyzSync des fonctions ci-dessus. Mais dans la mesure du possible, avec les E/S, il est préférable d'éviter les appels synchrones. Les appels dans le sous-système d'E/S prennent beaucoup de temps du point de vue de la CPU. Notez comme il est facile d’appeler lstat plutôt que lstatSync:

_// Is it a directory?
lstat('/the/path', function(err, stats) {
    if (!err && stats.isDirectory()) {
        // Yes it is
    }
});
_

Mais si vous avez besoin de la version synchrone, c'est là.

Mise à jour septembre 2012

La réponse ci-dessous d'il y a quelques années est maintenant un peu dépassée. La méthode actuelle consiste à utiliser fs.existsSync pour effectuer une vérification synchrone de l'existence d'un fichier/répertoire (ou bien sûr fs.exists pour une vérification asynchrone), plutôt que les versions path ci-dessous.

Exemple:

_var fs = require('fs');

if (fs.existsSync(path)) {
    // Do something
}

// Or

fs.exists(path, function(exists) {
    if (exists) {
        // Do something
    }
});
_

Mise à jour février 2015

Et nous voici en 2015 et les documents Node déclarent maintenant que _fs.existsSync_ (et _fs.exists_) "seront obsolètes". (Parce que les Node personnes pensent qu'il est idiot de vérifier si quelque chose existe avant de l'ouvrir, mais ce n'est pas la seule raison de vérifier si quelque chose existe!)

Nous sommes donc probablement revenus aux différentes méthodes stat ... Jusqu'à/sauf si cela change encore, bien sûr.

Mise à jour décembre 2015

Je ne sais pas depuis combien de temps il est là, mais il y a aussi fs.access(path, fs.F_OK, ...)/fs.accessSync(path, fs.F_OK) . Et au moins à partir d’octobre 2016, la _fs.stat_ documentation recommande d’utiliser _fs.access_ pour effectuer des vérifications d’existence ("Pour vérifier si un fichier existe sans le manipuler par la suite, fs.access() est recommandé. "). Mais notez que l'accès non disponible est considéré comme un erreur, donc ce serait probablement mieux si vous vous attendez à ce que le fichier soit accessible:

_var fs = require('fs');

try {
    fs.accessSync(path, fs.F_OK);
    // Do something
} catch (e) {
    // It isn't accessible
}

// Or

fs.access(path, fs.F_OK, function(err) {
    if (!err) {
        // Do something
    } else {
        // It isn't accessible
    }
});
_

Mise à jour décembre 2016

Vous pouvez utiliser fs.existsSync() :

_if (fs.existsSync(path)) {
    // Do something
}
_

Il est obsolète depuis plusieurs années, mais ne l’est plus. De la docs:

Notez que fs.exists() est obsolète, mais fs.existsSync() ne l’est pas. (Le paramètre callback de fs.exists() accepte les paramètres incohérents avec les autres rappels Node.js. fs.existsSync() n'utilise pas de rappel.)

2046
T.J. Crowder

En regardant la source, il existe une version synchrone de path.exists - path.existsSync. On dirait qu'il a été oublié dans les docs.

Mise à jour:

path.exists et path.existsSync sont maintenant obsolètes Veuillez utiliser fs.exists et fs.existsSync.

Mise à jour 2016:

fs.exists et fs.existsSync ont également été déconseillés . Utilisez fs.stat () ou fs.access () .

119
Jeff

À l'aide des API actuellement recommandées (à compter de 2015) (selon la docs Node _), voici ce que je fais:

var fs = require('fs');

function fileExists(filePath)
{
    try
    {
        return fs.statSync(filePath).isFile();
    }
    catch (err)
    {
        return false;
    }
}

En réponse à la question EPERM soulevée par @broadband dans les commentaires, cela soulève un bon point. fileExists () n'est probablement pas un bon moyen de penser à cela dans de nombreux cas, car fileExists () ne peut pas vraiment promettre un retour booléen. Vous pourrez peut-être déterminer définitivement que le fichier existe ou n’existe pas, mais vous pouvez également obtenir une erreur d’autorisation. L'erreur d'autorisations n'implique pas nécessairement que le fichier existe, car vous pourriez ne pas avoir l'autorisation d'accéder au répertoire contenant le fichier sur lequel vous vérifiez. Et bien sûr, vous pouvez rencontrer une autre erreur lors de la vérification de l'existence d'un fichier.

Donc mon code ci-dessus est vraiment doFileExistAndDoIHaveAccessToIt (), mais votre question pourrait être doFileNotExistAndCouldICreateIt (), ce qui serait une logique complètement différente (qui aurait besoin de prendre en compte une erreur EPERM, entre autres).

Alors que la réponse fs.existsSync répond directement à la question posée ici, ce n'est souvent pas ce que vous voulez (vous ne voulez pas simplement savoir si "quelque chose" existe sur un chemin, vous vous souciez probablement de savoir si le "chose" qui existe est un fichier ou un répertoire).

En bout de ligne, si vous vérifiez si un fichier existe, vous le faites probablement parce que vous avez l'intention de prendre des mesures en fonction du résultat, et que cette logique (la vérification et/ou l'action ultérieure) devrait tenir compte de l'idée. qu’une chose trouvée sur ce chemin peut être un fichier ou un répertoire, et que vous pouvez rencontrer EPERM ou d’autres erreurs en cours de vérification.

53
BobDickinson

Une autre mise à jour

Ayant besoin d’une réponse à cette question moi-même, j’ai cherché dans la documentation du noeud, il semble que vous devriez ne pas utiliser avec fs.exists, mais plutôt avec fs.open et avec outputted. erreur de détecter si un fichier n'existe pas:

des docs:

fs.exists () est un anachronisme et n'existe que pour des raisons historiques. Il ne devrait presque jamais y avoir de raison de l’utiliser dans votre propre code.

En particulier, vérifier si un fichier existe avant de l'ouvrir est un anti-modèle qui vous rend vulnérable aux conditions de concurrence: un autre processus peut supprimer le fichier entre les appels à fs.exists () et fs.open (). Il suffit d'ouvrir le fichier et de gérer l'erreur quand il n'y en a pas.

http://nodejs.org/api/fs.html#fs_fs_exists_path_callback

20
Melbourne2991

J'utilise la fonction ci-dessous pour tester si le fichier existe. Il attrape également d'autres exceptions. Donc, au cas où il y aurait des problèmes de droits, par exemple _chmod ugo-rwx filename_ ou dans Windows _Right Click -> Properties -> Security -> Advanced -> Permission entries: empty list .._ la fonction renvoie l'exception comme il se doit. Le fichier existe mais nous n'avons pas le droit d'y accéder. Il serait faux d’ignorer ce genre d’exceptions.

_function fileExists(path) {

  try  {
    return fs.statSync(path).isFile();
  }
  catch (e) {

    if (e.code == 'ENOENT') { // no such file or directory. File really does not exist
      console.log("File does not exist.");
      return false;
    }

    console.log("Exception fs.statSync (" + path + "): " + e);
    throw e; // something else went wrong, we don't have rights, ...
  }
}
_

Sortie d'exception, documentation sur les erreurs nodejs si le fichier n'existe pas:

_{
  [Error: ENOENT: no such file or directory, stat 'X:\\delsdfsdf.txt']
  errno: -4058,
  code: 'ENOENT',
  syscall: 'stat',
  path: 'X:\\delsdfsdf.txt'
}
_

Exception dans le cas où nous n'avons pas de droits sur le fichier, mais existe:

_{
  [Error: EPERM: operation not permitted, stat 'X:\file.txt']
  errno: -4048,
  code: 'EPERM',
  syscall: 'stat',
  path: 'X:\\file.txt'
}
_
11
broadband

fs.exists () est obsolète, ne l'utilisez pas https://nodejs.org/api/fs.html#fs_fs_exists_path_callback

Vous pouvez implémenter la méthode principale nodejs utilisée à ceci: https://github.com/nodejs/node-v0.x-archive/blob/master/lib/module.js#L86

function statPath(path) {
  try {
    return fs.statSync(path);
  } catch (ex) {}
  return false;
}

cela retournera l'objet de statistiques, puis une fois que vous avez l'objet de statistiques, vous pouvez essayer

var exist = statPath('/path/to/your/file.js');
if(exist && exist.isFile()) {
  // do something
}
5
gsalgadotoledo

Certaines réponses ici disent que fs.exists et fs.existsSync sont tous deux obsolètes. Selon les docs, ce n'est plus le cas. Seul fs.exists est maintenant désactivé:

Notez que fs.exists () est obsolète, mais fs.existsSync () ne l’est pas. (Le paramètre callback de fs.exists () accepte les paramètres incohérents avec les autres rappels de Node.js. Fs.existsSync () n'utilise pas de rappel.)

Vous pouvez donc utiliser en toute sécurité fs.existsSync () pour vérifier de manière synchrone si un fichier existe.

4
jstice4all

Le module path ne fournit pas de version synchrone de path.exists, vous devez donc vous débrouiller avec le module fs.

La chose la plus rapide que je puisse imaginer est d’utiliser fs.realpathSync, ce qui jettera une erreur que vous devez intercepter, vous devez donc créer votre propre fonction d’emballage avec un try/catch.

2
Ivo Wetzel

L'utilisation de tests fileSystem (fs) déclenchera des objets d'erreur qu'il vous faudra ensuite inclure dans une instruction try/catch. Épargnez-vous des efforts et utilisez une fonctionnalité introduite dans la branche 0.4.x.

var path = require('path');

var dirs = ['one', 'two', 'three'];

dirs.map(function(dir) {
  path.exists(dir, function(exists) {
    var message = (exists) ? dir + ': is a directory' : dir + ': is not a directory';
    console.log(message);
  });
});
0
user1248475

Les documents sur fs.stat() indiquent qu'il faut utiliser fs.access() si vous n'allez pas manipuler le fichier. Il n'a pas donné de justification, pourrait être un usage plus rapide ou moins mémorable?

J'utilise node pour l'automatisation linéaire. Je pensais donc partager la fonction que j'utilise pour tester l'existence d'un fichier.

var fs = require("fs");

function exists(path){
    //Remember file access time will slow your program.
    try{
        fs.accessSync(path);
    } catch (err){
        return false;
    }
    return true;
}
0
Grallen