1466 votes

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 ?

72 votes

Les opérations synchrones sont idéales pour effectuer des opérations ponctuelles sur des fichiers/répertoires avant de renvoyer un module. Par exemple, l'amorçage d'un fichier de configuration.

1 votes

@PaulDraper avec un cachet chaud n'est pas vrai dans tous les cas.

22 votes

Quelles que soient les performances, il arrive parfois que l'on veuille l'exécuter de manière synchronisée pour l'expérience du développeur. Par exemple, si vous utilisez Node pour un script de traitement de données qui, par conception, devrait être bloquant, dans ce cas, l'asynchronisme est nécessaire. exists ne fait qu'ajouter des rappels inutiles.

0voto

Yairopro Points 1360

Vous pouvez utiliser graph-fs

directory.exists // boolean

-1voto

JavaScriptDude Points 140

Voici une solution simple pour cela :

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

Utilisation :

  • Fonctionne à la fois 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

Ejemplo:

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 d'utiliser l'opérateur === pour tester si le retour est égal à faux. Il n'y a aucune raison logique pour 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 ni de baisse de performance. Du point de vue de l'API, fs.exists() semble être la solution la plus élégante.

1 votes

@Dan, merci. J'ai supprimé le texte tronqué. Je ne me rappelle pas quelle était la note. Si cela me revient, j'ajouterai des notes.

1 votes

Np. Je supprime mon commentaire.

-2voto

jgmjgm Points 36

D'après les réponses, il semble qu'il n'y ait pas de support officiel de l'API pour cela (comme une vérification directe et explicite). De nombreuses réponses indiquent qu'il faut utiliser stat, mais elles ne sont pas strictes. Nous ne pouvons pas supposer, par exemple, que toute erreur lancée par stat signifie que quelque chose n'existe pas.

Disons que nous essayons avec quelque chose qui n'existe pas :

$ node -e 'require("fs").stat("god",err=>console.log(err))'
{ Error: ENOENT: no such file or directory, stat 'god' errno: -2, code: 'ENOENT', syscall: 'stat', path: 'god' }

Essayons avec quelque chose qui existe mais auquel nous n'avons pas accès :

$ mkdir -p fsm/appendage && sudo chmod 0 fsm
$ node -e 'require("fs").stat("fsm/appendage",err=>console.log(err))'
{ Error: EACCES: permission denied, stat 'access/access' errno: -13, code: 'EACCES', syscall: 'stat', path: 'fsm/appendage' }

Au minimum, vous voudrez :

let dir_exists = async path => {
    let stat;
    try {
       stat = await (new Promise(
           (resolve, reject) => require('fs').stat(path,
               (err, result) => err ? reject(err) : resolve(result))
       ));
    }
    catch(e) {
        if(e.code === 'ENOENT') return false;
        throw e;
    }

    if(!stat.isDirectory())
        throw new Error('Not a directory.');

    return true;
};

La question n'est pas claire quant à savoir si vous voulez réellement qu'elle soit syncrone ou si vous voulez seulement qu'elle soit écrite comme si elle était syncrone. Cet exemple utilise await/async pour qu'il soit écrit de manière synchrone mais s'exécute de manière asynchrone.

Cela signifie que vous devez l'appeler comme tel au niveau supérieur :

(async () => {
    try {
        console.log(await dir_exists('god'));
        console.log(await dir_exists('fsm/appendage'));
    }
    catch(e) {
        console.log(e);
    }
})();

Une alternative consiste à utiliser .then et .catch sur la promesse renvoyée par l'appel asynchrone si vous en avez besoin plus tard.

Si vous voulez vérifier si quelque chose existe, il est bon de s'assurer qu'il s'agit du bon type de chose, comme un répertoire ou un fichier. Ceci est inclus dans l'exemple. Si ce n'est pas autorisé à être un lien symbolique, vous devez utiliser lstat au lieu de stat car stat traverse automatiquement les liens.

Vous pouvez remplacer tout le code async to sync ici et utiliser statSync à la place. Cependant, attendez-vous à ce qu'une fois que async et await seront universellement supportés, les appels de synchronisation deviendront redondants et seront finalement dépréciés (sinon, vous devrez les définir partout et en amont de la chaîne, comme avec async, ce qui les rendrait vraiment inutiles).

1 votes

La question initiale ne le précise pas. Je démontre également comment faire les choses sans ambiguïté. De nombreuses réponses pourraient induire des bogues en raison du manque de clarté. Les gens veulent souvent programmer les choses de façon à ce qu'elles paraissent synchrones mais ne veulent pas nécessairement une exécution synchrone. statSync n'est pas la même chose que le code que j'ai démontré. Les deux comptes rendus de ce qui est réellement souhaité sont ambigus, donc vous ne faites qu'imposer vos interprétations personnelles. Si vous trouvez une réponse que vous ne comprenez pas, il serait préférable de demander simplement dans les commentaires ou par message personnel pour déterminer quelles modifications sont nécessaires.

1 votes

Si vous voulez, vous pouvez aussi voler mon échantillon de code, le nommer de manière appropriée, le mettre sur github, l'ajouter à npm et alors la réponse ne sera qu'une ligne/un lien :D.

0 votes

Le code est court pour les besoins de l'exemple, mais vous pouvez soumettre une suggestion d'édition pour inclure && !isFile ou une vérification des liens symboliques, etc. Comme je l'ai déjà souligné, ma réponse satisfait une interprétation de la question et ne fait pas la même chose que votre proposition d'une ligne.

-2voto

SwiftNinjaPro Points 79

Il est fort probable que si vous voulez savoir si un fichier existe, vous prévoyez de le demander s'il existe.

function getFile(path){
    try{
        return require(path);
    }catch(e){
        return false;
    }
}

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