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




(9)

Solution Async Promise (bluebirdjs)

Pour ceux qui utilisent bluebirdjs et nodejs 7. Le meilleur moyen de renvoyer une promesse booléenne:

function fileExists(path){
  return fs.accessAsync(path, fs.constants.F_OK) //F_OK checks if file is visible, is default does no need to be specified.
         .then(err => !err);
}

les documents: fs.access

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


Certaines réponses indiquent que fs.exists et fs.existsSync sont tous deux obsolètes. D'après les docs, ce n'est plus vrai. Seul fs.exists est maintenant déprécié:

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

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


En regardant la source, il y a une version synchrone de path.exists - path.existsSync . On dirait que ça a été manqué dans les docs.

Mettre à 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épréciés . Utilisez fs.stat() ou fs.access() .


En utilisant les API actuellement recommandées (à partir de 2015) (par les 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 d'y penser dans de nombreux cas, car fileExists () ne peut pas vraiment promettre un retour booléen. Vous pouvez être en mesure de déterminer définitivement que le fichier existe ou n'existe pas, mais vous pouvez également obtenir une erreur d'autorisations. L'erreur d'autorisation n'implique pas nécessairement que le fichier existe, car vous pourriez manquer de l'autorisation du répertoire contenant le fichier sur lequel vous vérifiez. Et bien sûr, il y a des chances que vous rencontriez une autre erreur en vérifiant l'existence d'un fichier.

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

Alors que la réponse de 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 la "chose" qui existe est un fichier ou un répertoire).

L'essentiel est que si vous vérifiez si un fichier existe, vous le faites probablement parce que vous avez l'intention de prendre une action basée sur le résultat, et cette logique (la vérification et / ou l'action subséquente) 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 dans le processus de vérification.


L'utilisation de tests systemSystem (fs) déclenchera des objets d'erreur, que vous devrez ensuite placer dans une instruction try / catch. Épargnez-vous quelques efforts et utilisez une fonction introd 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);
  });
});

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

Réponse actuelle

Vous pouvez utiliser fs.existsSync() :

var fs = require('fs');
if (fs.existsSync(path)) {
    // Do something
}

Il a été déprécié pendant plusieurs années, mais ne l'est plus. De la docs:

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

Vous avez spécifiquement demandé une vérification synchrone , mais si vous pouvez utiliser une vérification asynchrone à la place (généralement avec les E / S), utilisez fs.access (puisque exists est obsolète).

Réponses historiques

Voici les réponses historiques dans l'ordre chronologique:

  • Réponse initiale de 2010
    ( stat / statSync ou lstat / lstatSync )
  • Mise à jour septembre 2012
    ( exists / existsSync )
  • Mise à jour février 2015
    (Notant la dépréciation imminente de exists / existsSync , donc nous sommes probablement de retour à stat / statSync ou lstat / lstatSync )
  • Mise à jour 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, c'est une erreur; docs pour fs.stat recommande d'utiliser fs.access si vous devez vérifier l'existence sans l'ouvrir)
  • Mise à jour 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 docs ), ce qui vous donne un objet fs.Stats . En général, si une version synchrone d'une fonction est disponible, elle aura 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, dans l'affirmative, s'il s'agit d'un fichier ou d'un répertoire (ou dans certains systèmes de fichiers, un lien symbolique, un périphérique bloc, un périphérique caractère, etc.), par exemple est un directeur:

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 si c'est un fichier, il y a isFile ; s'il s'agit d'un périphérique bloc, il y a isBlockDevice , etc., etc. Notez le try/catch ; il jette une erreur 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 version, fs.existsSync ) comme indiqué par user618408 :

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

Il ne nécessite pas d' try/catch , mais ne vous donne aucune information sur ce qu'est la chose, juste que c'est là. path.existsSync était obsolète depuis longtemps.

Note de côté: 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 l'unité centrale. Notez combien 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émodé. La méthode actuelle consiste à utiliser fs.existsSync() pour effectuer une vérification synchrone de l'existence du fichier / répertoire (ou, bien sûr, fs.exists pour une vérification asynchrone), plutôt que les versions de 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 docs de Node disent maintenant que fs.existsSync (et fs.exists ) "sera déprécié". (Parce que les gens de Node pensent qu'il est stupide de vérifier si quelque chose existe avant de l'ouvrir, ce qui est le cas, mais ce n'est pas la seule raison pour vérifier si quelque chose existe!)

Donc, nous sommes probablement de retour aux différentes méthodes stat ... Jusqu'à / à moins que cela ne change encore, bien sûr.

Mise à jour décembre 2015

Je ne sais pas depuis combien de temps il existe, mais il y a aussi fs.access . Et au moins à partir d'octobre 2016, la documentation fs.stat 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é d'utiliser fs.access() " ). Mais notez que l'accès n'est pas disponible est considéré comme une erreur , donc ce serait probablement mieux si vous attendez 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 a été déprécié pendant plusieurs années, mais ne l'est plus. De la docs:

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


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

J'utilise un noeud pour l'automatisation linéaire, donc j'ai pensé 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;
}

Voici une solution d'encapsulation simple pour cela:

var fs = require('fs')
function getFileRealPath(s){
    try {return fs.realpathSync(s);} catch(e){return false;}
}

Usage:

  • Fonctionne pour les répertoires et les fichiers
  • Si l'élément existe, il renvoie le chemin d'accès au fichier ou au répertoire
  • Si l'élément n'existe pas, il renvoie false

Exemple:

var realPath,pathToCheck='<your_dir_or_file>'
if( (realPath=getFileRealPath(pathToCheck)) === false){
    console.log('file/dir not found: '+pathToCheck);
} else {
    console.log('file/dir exists: '+realPath);
}

Assurez-vous que vous utilisez l'opérateur === pour tester si return vaut false. Il n'y a aucune raison logique que fs.realpathSync () renvoie false dans des conditions de travail correctes, donc je pense que cela devrait fonctionner à 100%.

Je préférerais voir une solution qui ne génère pas d'erreur et de coup de performance qui en résulte. Du point de vue de l'API, fs.exists () semble être la solution la plus élégante.


Autre mise à jour

Ayant besoin d'une réponse à cette question moi-même j'ai regardé les documents du nœud, semble que vous ne devriez pas utiliser fs.exists, utilisez plutôt fs.open et utilisez outputted error pour détecter si un fichier n'existe pas:

à partir 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-pattern qui vous rend vulnérable aux conditions de course: 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 elle n'est pas là.

fs.exists





node.js