Verifique sincrónicamente si el archivo/directorio existe en Node.js
¿Cómo puedo verificar sincrónicamente, usando node.js , si existe un archivo o directorio?
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, perofs.existsSync()
no lo está. (El parámetro de devolución de llamadafs.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 async
funciones o fs.access
(ya que exists
está en desuso ) si no:
En una async
funció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
/statSync
olstat
/lstatSync
) - Actualización septiembre 2012
(exists
/existsSync
) - Actualización de febrero de 2015
(observando la inminente desaprobación deexists
/existsSync
, por lo que probablemente volvamos astat
/statSync
olstat
/lstatSync
) - Actualización de diciembre de 2015
(también hayfs.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 recomiendafs.stat
usar los documentosfs.access
si necesita verificar su existencia sin abrir) - La actualización de diciembre de 2016
fs.exists()
todavía está en desuso, perofs.existsSync()
ya no está en desuso. Entonces puedes usarlo de manera segura ahora.
Respuesta original de 2010:
Puede utilizar statSync
o lstatSync
( enlace de documentos ), que le proporcionará un fs.Stats
objeto . 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 Sync
final. También lo statSync
es la versión síncrona de stat
; lstatSync
es la versión síncrona de lstat
, etc.
lstatSync
le 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/catch
pero no le brinda información sobre qué es, solo que está ahí. path.existsSync
quedó obsoleto hace mucho tiempo.
Nota al margen: usted preguntó expresamente cómo verificar sincrónicamente , por lo que usé las xyzSync
versiones 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 lstat
en 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.existsSync
para realizar una verificación sincrónica de la existencia de archivos/directorios (o, por supuesto, fs.exists
para una verificación asincrónica), en lugar de las path
versiones 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 stat
mé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.stat
documentación recomienda utilizar fs.access
para 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, perofs.existsSync()
no lo está. (El parámetro de devolución de llamadafs.exists()
acepta parámetros que son inconsistentes con otras devoluciones de llamada de Node.js.fs.existsSync()
No utiliza una devolución de llamada).
Mirando la fuente, hay una versión sincrónica de path.exists
- path.existsSync
. Parece que se perdió en los documentos.
Actualizar:
path.exists
y path.existsSync
ahora están en desuso . Por favor use .fs.exists
yfs.existsSync
Actualización 2016:
fs.exists
y quedado obsoletos . Utilice fs.stat() o fs.access() en su lugar.fs.existsSync
también han
Actualización 2019:
usar fs.existsSync
. No está en desuso.
https://nodejs.org/api/fs.html#fs_fs_existssync_path
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.
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