Comment puis-je vérifier de manière synchrone, à l'aide de node.js , si un fichier ou un répertoire existe?
exists
ajoute simplement des rappels inutiles.
Comment puis-je vérifier de manière synchrone, à l'aide de node.js , si un fichier ou un répertoire existe?
exists
ajoute simplement des rappels inutiles.
Réponses:
La réponse à cette question a changé au fil des ans. La réponse actuelle est ici en haut, suivie des différentes réponses au fil des années par ordre chronologique:
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 documentation:
Notez que
fs.exists()
c'est obsolète, mais cefs.existsSync()
n'est pas le cas. (Le paramètre de rappel pourfs.exists()
accepter les paramètres qui ne sont pas cohérents avec les autres rappels Node.js. N'utilisefs.existsSync()
pas de rappel.)
Vous avez spécifiquement demandé une vérification synchrone , mais si vous pouvez utiliser une vérification asynchrone à la place (généralement mieux avec les E / S), utilisez fs.promises.access
si vous utilisez des async
fonctions ou fs.access
(car exists
est déconseillé ) sinon:
Dans une async
fonction:
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
}
});
Voici les réponses historiques par ordre chronologique:
stat
/ statSync
ou lstat
/ lstatSync
)exists
/ existsSync
)exists
/ existsSync
, nous sommes donc probablement de retour à stat
/ statSync
ou lstat
/ lstatSync
)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; documents à fs.stat
recommander fs.access
si vous devez vérifier l'existence sans ouvrir)fs.exists()
est toujours obsolète mais fs.existsSync()
n'est plus obsolète. Vous pouvez donc l'utiliser en toute sécurité maintenant.Vous pouvez utiliser statSync
ou lstatSync
( lien docs ), qui vous donne un fs.Stats
objet . 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. Il en statSync
va de même pour la version synchrone de stat
; lstatSync
est la version synchrone de lstat
, etc.
lstatSync
vous indique à la fois si quelque chose existe, et si oui, s'il s'agit d'un fichier ou d'un répertoire (ou dans certains systèmes de fichiers, un lien symbolique, un bloc, un caractère, etc.), par exemple si vous avez besoin de savoir s'il existe et s'il est 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 y a isFile
; s'il s'agit d'un périphérique bloc, il y a isBlockDevice
, etc., etc. Notez le try/catch
; il renvoie une erreur si l'entrée n'existe pas du tout.
Si vous ne vous inquiétez pas ce que l'entrée est et que vous voulez seulement savoir si elle existe, vous pouvez utiliser path.existsSync
(ou plus tard fs.existsSync
) comme indiqué par user618408 :
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 ce qu'est la chose, juste qu'elle est là. path.existsSync
a été dépréciée depuis longtemps.
Note latérale: Vous avez expressément demandé comment vérifier de manière synchrone , j'ai donc utilisé les xyzSync
versions 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 du processeur. 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, elle est là.
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 path
versions ci-dessous.
Exemple:
var fs = require('fs');
if (fs.existsSync(path)) {
// Do something
}
// Or
fs.exists(path, function(exists) {
if (exists) {
// Do something
}
});
Et nous voici en 2015 et les docs Node disent maintenant que fs.existsSync
(et fs.exists
) "sera déprécié". (Parce que les gens du Node pensent qu'il est stupide de vérifier si quelque chose existe avant de l'ouvrir, ce qu'il est; mais ce n'est pas la seule raison de vérifier si quelque chose existe!)
Donc, nous sommes probablement de retour aux différentes stat
méthodes ... Jusqu'à / à moins que cela ne change encore une fois, bien sûr.
Je ne sais pas depuis combien de temps il y est, mais il y a aussi fs.access(path, fs.F_OK, ...)
/fs.accessSync(path, fs.F_OK)
. Et au moins depuis octobre 2016, la fs.stat
documentation recommande d'utiliser fs.access
pour faire 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 une 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
}
});
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 documentation:
Notez que
fs.exists()
c'est obsolète, mais cefs.existsSync()
n'est pas le cas. (Le paramètre de rappel pourfs.exists()
accepter les paramètres qui ne sont pas cohérents avec les autres rappels Node.js. N'utilisefs.existsSync()
pas de rappel.)
open
appel et de gérer l'exception ou peu importe si le fichier n'était pas a trouvé. Après tout, le monde réel est chaotique: si vous vérifiez d'abord et qu'il est là, cela ne signifie pas qu'il sera toujours là lorsque vous essayez de l'ouvrir; si vous vérifiez d'abord et qu'il n'est pas là, cela ne signifie pas qu'il ne sera pas là un instant plus tard. Des choses comme ça ressemblent à des cas marginaux, mais elles reviennent tout le temps . Donc, si vous allez ouvrir, inutile de vérifier d'abord.
En regardant la source, il existe une version synchrone de path.exists
- path.existsSync
. On dirait que ça a été oublié dans la documentation.
path.exists
et path.existsSync
sont désormais obsolètes . Veuillez utiliser .fs.exists
etfs.existsSync
fs.exists
et été dépréciés . Utilisez plutôt fs.stat () ou fs.access () .fs.existsSync
ont également
utiliser fs.existsSync
. Ce n'est pas obsolète.
https://nodejs.org/api/fs.html#fs_fs_existssync_path
fs.existsSync
.
exists
fonction:is-there
fs.exists
que comme obsolètes alors qu'ils fs.existsSync
ne le sont pas!
En utilisant les API actuellement recommandées (à partir de 2015) (selon la documentation 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 au problème EPERM soulevé 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'autorisations n'implique pas nécessairement que le fichier existe, car vous pourriez ne pas avoir l'autorisation sur le répertoire contenant le fichier sur lequel vous vérifiez. Et bien sûr, il est possible que vous rencontriez une autre erreur lors de la vérification de l'existence du fichier.
Donc, mon code ci-dessus est vraiment doesFileExistAndDoIHaveAccessToIt (), mais votre question pourrait être doesFileNotExistAndCouldICreateIt (), ce qui serait une logique complètement différente (qui devrait tenir compte d'une erreur EPERM, entre autres).
Bien que la réponse fs.existsSync réponde directement à la question posée ici, ce ne sera souvent pas ce que vous voulez (vous ne voulez pas simplement savoir si "quelque chose" existe sur un chemin, vous vous demandez probablement si la "chose" qui existe est un fichier ou un répertoire).
L'essentiel, c'est que si vous vérifiez pour voir 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 la 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 dans le processus de vérification.
file.exists()
util pour les 3% et nous obliger à la place à envelopper dans une prise d'essai? Soyez réel ... Salope du jour.
Une autre mise à jour
Ayant moi-même besoin d'une réponse à cette question, j'ai recherché les documents du nœud, il semble que vous ne devriez pas utiliser fs.exists, utilisez plutôt fs.open et utilisez une erreur de sortie pour détecter si un fichier n'existe pas:
à partir des documents:
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 (). Ouvrez simplement le fichier et gérez l'erreur lorsqu'il n'est pas là.
J'utilise la fonction ci-dessous pour tester si le fichier existe. Il intercepte également d'autres exceptions. Donc, dans le cas où il y a des problèmes de droits, par exemple, chmod ugo-rwx filename
ou dans Windows, la
Right Click -> Properties -> Security -> Advanced -> Permission entries: empty list ..
fonction renvoie une 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 type 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 des erreurs nodejs dans le cas où 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 qui existe:
{
[Error: EPERM: operation not permitted, stat 'X:\file.txt']
errno: -4048,
code: 'EPERM',
syscall: 'stat',
path: 'X:\\file.txt'
}
fs.exists () est déconseillé ne l'utilisez pas https://nodejs.org/api/fs.html#fs_fs_exists_path_callback
Vous pouvez implémenter la manière principale de nodejs utilisée ici: 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 renverra l'objet stats puis une fois que vous aurez l'objet stats vous pourrez essayer
var exist = statPath('/path/to/your/file.js');
if(exist && exist.isFile()) {
// do something
}
Certaines réponses ici le disent fs.exists
et fs.existsSync
sont toutes deux obsolètes. Selon les documents, cela n'est plus vrai. Seul fs.exists
est désormais déprécié:
Notez que fs.exists () est déconseillé, mais fs.existsSync () ne l'est pas. (Le paramètre de rappel de fs.exists () accepte des paramètres qui ne sont pas cohérents avec les autres rappels 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.
Le path
module ne fournit pas de version synchrone de path.exists
donc vous devez faire le tour avec le fs
module.
La chose la plus rapide que j'imagine est d'utiliser fs.realpathSync
qui générera une erreur que vous devrez intercepter, vous devez donc créer votre propre fonction wrapper avec un try / catch.
L'utilisation de tests fileSystem (fs) déclenchera des objets d'erreur, que vous devrez ensuite encapsuler dans une instruction try / catch. Épargnez-vous un peu d'effort 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);
});
});
Les documents sur fs.stat()
indiquent à utiliser fs.access()
si vous n'allez pas manipuler le fichier. Il n'a pas donné de justification, pourrait être une utilisation plus rapide ou moins de la mémoire?
J'utilise node pour l'automatisation linéaire, j'ai donc 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;
}
mis à jour une réponse pour ces personnes indiquant «correctement» qu'il ne répond pas directement à la question, apportez davantage une option alternative.
fs.existsSync('filePath')
voir aussi les documents ici .
Renvoie vrai si le chemin existe, faux sinon.
Dans un contexte asynchrone, vous pouvez simplement écrire la version asynchrone dans la méthode de synchronisation en utilisant le await
mot clé. Vous pouvez simplement transformer la méthode de rappel asynchrone en promesse comme ceci:
function fileExists(path){
return new Promise((resolve, fail) => fs.access(path, fs.constants.F_OK,
(err, result) => err ? fail(err) : resolve(result))
//F_OK checks if file is visible, is default does no need to be specified.
}
async function doSomething() {
var exists = await fileExists('filePath');
if(exists){
console.log('file exists');
}
}
la documentation sur access ().
function asyncFileExists(path) { //F_OK checks if file is visible, is default does no need to be specified. return new Promise(function (res, rej) { fs.access( path, fs.constants.F_OK, function (err) { err ? rej(err) : res(true); }, ); }); }
Il y a de fortes chances que si vous voulez savoir si un fichier existe, vous prévoyez de l'exiger s'il le fait.
function getFile(path){
try{
return require(path);
}catch(e){
return false;
}
}
Voici une solution d'emballage simple pour cela:
var fs = require('fs')
function getFileRealPath(s){
try {return fs.realpathSync(s);} catch(e){return false;}
}
Usage:
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 d'utiliser l'opérateur === pour tester si return est égal à 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 les performances qui en résultent. Du point de vue de l'API, fs.exists () semble être la solution la plus élégante.
D'après les réponses, il semble qu'il n'y ait pas de support API officiel pour cela (comme dans une vérification directe et explicite). Beaucoup de réponses disent 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' }
Vous voudrez au moins:
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 de 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 wait / async pour qu'il ne soit écrit que de manière syncrone mais s'exécute de manière asyncrone.
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 loin.
Si vous voulez vérifier si quelque chose existe, c'est une bonne pratique de vous assurer que c'est le bon type de chose comme un répertoire ou un fichier. Ceci est inclus dans l'exemple. S'il n'est pas autorisé à être un lien symbolique, vous devez utiliser lstat au lieu de stat car stat traversera automatiquement les liens.
Vous pouvez remplacer tous les codes asynchrones pour synchroniser le code ici et utiliser statSync à la place. Cependant, attendez-vous à ce qu'une fois que l'async et l'attente deviennent universellement pris en charge, les appels de synchronisation deviendront redondants pour être éventuellement amortis (sinon vous devrez les définir partout et en amont, tout comme avec async, ce qui le rend vraiment inutile).