Verifique sincrónicamente si el archivo/directorio existe en Node.js

Resuelto asked hace 14 años • 19 respuestas

¿Cómo puedo verificar sincrónicamente, usando node.js , si existe un archivo o directorio?

 avatar Dec 19 '10 18:12
Aceptado

La respuesta a esta pregunta ha cambiado a lo largo de los años. La respuesta actual está aquí en la parte superior, seguida de las distintas respuestas a lo largo de los años en orden cronológico:

Respuesta actual

Puedes usar fs.existsSync():

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

Estuvo en desuso durante varios años, pero ya no lo está. De los documentos:

Tenga en cuenta que fs.exists()está en desuso, pero fs.existsSync()no lo está. (El parámetro de devolución de llamada fs.exists()acepta parámetros que son inconsistentes con otras devoluciones de llamada de Node.js. fs.existsSync()No utiliza una devolución de llamada).

Ha solicitado específicamente una verificación sincrónica , pero si puede usar una verificación asincrónicafs.promises.access en su lugar (generalmente mejor con E/S), úsela si está usando asyncfunciones o fs.access(ya que existsestá en desuso ) si no:

En una asyncfunción:

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

O con una devolución de llamada:

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

Respuestas históricas

Aquí están las respuestas históricas en orden cronológico:

  • Respuesta original de 2010
    ( stat/ statSynco lstat/ lstatSync)
  • Actualización septiembre 2012
    ( exists/ existsSync)
  • Actualización de febrero de 2015
    (observando la inminente desaprobación de exists/ existsSync, por lo que probablemente volvamos a stat/ statSynco lstat/ lstatSync)
  • Actualización de diciembre de 2015
    (también hay fs.access(path, fs.F_OK, function(){})/ fs.accessSync(path, fs.F_OK), pero tenga en cuenta que si el archivo/directorio no existe, es un error; se recomienda fs.statusar los documentos fs.accesssi necesita verificar su existencia sin abrir)
  • La actualización de diciembre de 2016
    fs.exists() todavía está en desuso, pero fs.existsSync()ya no está en desuso. Entonces puedes usarlo de manera segura ahora.

Respuesta original de 2010:

Puede utilizar statSynco lstatSync( enlace de documentos ), que le proporcionará un fs.Statsobjeto . En general, si hay disponible una versión síncrona de una función, tendrá el mismo nombre que la versión asíncrona al Syncfinal. También lo statSynces la versión síncrona de stat; lstatSynces la versión síncrona de lstat, etc.

lstatSyncle dice si algo existe y, de ser así, si es un archivo o un directorio (o en algunos sistemas de archivos, un enlace simbólico, un dispositivo de bloque, un dispositivo de caracteres, etc.), por ejemplo, si necesita saber si existe y está un directorio:

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) {
    // ...
}

...y de manera similar, si es un archivo, hay isFile; si es un dispositivo de bloque, hay isBlockDevice, etc., etc. Tenga en cuenta el try/catch; arroja un error si la entrada no existe en absoluto.

Si no le importa cuál es la entrada y solo quiere saber si existe, puede usar path.existsSync(o con la última fs.existsSync) como lo indica el usuario618408 :

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

No requiere un try/catchpero no le brinda información sobre qué es, solo que está ahí. path.existsSyncquedó obsoleto hace mucho tiempo.


Nota al margen: usted preguntó expresamente cómo verificar sincrónicamente , por lo que usé las xyzSyncversiones de las funciones anteriores. Pero siempre que sea posible, con E/S, es mejor evitar las llamadas sincrónicas. Las llamadas al subsistema de E/S toman mucho tiempo desde el punto de vista de la CPU. Tenga en cuenta lo fácil que es llamar lstaten lugar de lstatSync:

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

Pero si necesitas la versión sincrónica, la tienes ahí.

Actualización septiembre 2012

La siguiente respuesta de hace un par de años ahora está un poco desactualizada. La forma actual es utilizar fs.existsSyncpara realizar una verificación sincrónica de la existencia de archivos/directorios (o, por supuesto, fs.existspara una verificación asincrónica), en lugar de las pathversiones siguientes.

Ejemplo:

var fs = require('fs');

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

// Or

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

Actualización febrero 2015

Y aquí estamos en 2015 y los documentos de Node ahora dicen que fs.existsSync(y fs.exists) "quedará obsoleto". (Porque la gente de Node piensa que es tonto verificar si algo existe antes de abrirlo, lo cual es; ¡pero esa no es la única razón para verificar si algo existe!)

Así que probablemente volvamos a los diversos statmétodos... Hasta/a menos que esto cambie una vez más, por supuesto.

Actualización diciembre 2015

No sé cuánto tiempo lleva ahí, pero también está fs.access(path, fs.F_OK, ...)/fs.accessSync(path, fs.F_OK) . Y al menos a partir de octubre de 2016, la fs.statdocumentación recomienda utilizar fs.accesspara realizar comprobaciones de existencia ( " Se recomienda comprobar si un archivo existe sin manipularlo despuésfs.access() " ). Pero tenga en cuenta que el hecho de que el acceso no esté disponible se considera un error , por lo que probablemente sería mejor si espera que se pueda acceder al archivo:

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
    }
});

Actualización diciembre 2016

Puedes usar fs.existsSync():

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

Estuvo en desuso durante varios años, pero ya no lo está. De los documentos:

Tenga en cuenta que fs.exists()está en desuso, pero fs.existsSync()no lo está. (El parámetro de devolución de llamada fs.exists()acepta parámetros que son inconsistentes con otras devoluciones de llamada de Node.js. fs.existsSync()No utiliza una devolución de llamada).

T.J. Crowder avatar Dec 19 '2010 11:12 T.J. Crowder

Mirando la fuente, hay una versión sincrónica de path.exists- path.existsSync. Parece que se perdió en los documentos.

Actualizar:

path.existsy path.existsSyncahora están en desuso . Por favor use fs.existsyfs.existsSync .

Actualización 2016:

fs.exists y fs.existsSynctambién han quedado obsoletos . Utilice fs.stat() o fs.access() en su lugar.

Actualización 2019:

usar fs.existsSync. No está en desuso. https://nodejs.org/api/fs.html#fs_fs_existssync_path

Jeff avatar Feb 15 '2011 19:02 Jeff

Usando las API recomendadas actualmente (a partir de 2015) (según los documentos de Node), esto es lo que hago:

var fs = require('fs');

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

En respuesta al problema de EPERM planteado por @broadband en los comentarios, eso plantea un buen punto. fileExists() probablemente no sea una buena manera de pensar en esto en muchos casos, porque fileExists() realmente no puede prometer un retorno booleano. Es posible que pueda determinar definitivamente si el archivo existe o no, pero también puede recibir un error de permisos. El error de permisos no implica necesariamente que el archivo exista, porque es posible que le falten permisos para el directorio que contiene el archivo que está verificando. Y, por supuesto, existe la posibilidad de que encuentre algún otro error al verificar la existencia del archivo.

Entonces, mi código anterior es realmente DoesFileExistAndDoIHaveAccessToIt(), pero su pregunta podría ser DoesFileNotExistAndCouldICreateIt(), que sería una lógica completamente diferente (que tendría que tener en cuenta un error de EPERM, entre otras cosas).

Si bien la respuesta de fs.existsSync aborda la pregunta formulada aquí directamente, a menudo eso no será lo que desea (no solo desea saber si "algo" existe en una ruta, probablemente le interese si la "cosa" lo que existe es un archivo o un directorio).

La conclusión es que si está verificando si existe un archivo, probablemente lo esté haciendo porque tiene la intención de realizar alguna acción en función del resultado, y esa lógica (la verificación y/o la acción posterior) debe adaptarse a la idea. que algo encontrado en esa ruta puede ser un archivo o un directorio, y que puede encontrar EPERM u otros errores en el proceso de verificación.

BobDickinson avatar Sep 23 '2015 21:09 BobDickinson

Otra actualización

Al necesitar una respuesta a esta pregunta, busqué los documentos del nodo, parece que no debería usar fs.exists, en su lugar use fs.open y use el error generado para detectar si un archivo no existe:

de los documentos:

fs.exists() is an anachronism and exists only for historical reasons. There should almost never be a reason to use it in your own code.

In particular, checking if a file exists before opening it is an anti-pattern that leaves you vulnerable to race conditions: another process may remove the file between the calls to fs.exists() and fs.open(). Just open the file and handle the error when it's not there.

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

Melbourne2991 avatar Jun 07 '2014 04:06 Melbourne2991