¿Cómo puedo verificar sincrónicamente, usando node.js , si existe un archivo o directorio?
existssolo agrega devoluciones de llamada innecesarias.
¿Cómo puedo verificar sincrónicamente, usando node.js , si existe un archivo o directorio?
existssolo agrega devoluciones de llamada innecesarias.
Respuestas:
La respuesta a esta pregunta ha cambiado con los años. La respuesta actual está aquí en la parte superior, seguida de varias respuestas a lo largo de los años en orden cronológico:
Puedes usar fs.existsSync():
const fs = require("fs"); // Or `import fs from "fs";` with ESM
if (fs.existsSync(path)) {
// Do something
}
Fue en desuso durante varios años, pero ya no lo es. De los documentos:
Tenga en cuenta que
fs.exists()está en desuso, perofs.existsSync()no lo está. (El parámetro de devolución de llamada parafs.exists()aceptar 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ónica en su lugar (generalmente mejor con E / S), use fs.promises.accesssi está utilizando asyncfunciones o fs.access(dado 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
}
});
Aquí están las respuestas históricas en orden cronológico:
stat/ statSynco lstat/ lstatSync)exists/ existsSync)exists/ existsSync, por lo que probablemente volvamos a stat/ statSynco lstat/ lstatSync)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; documentos para fs.statrecomendar usar fs.accesssi necesita verificar la existencia sin abrir)fs.exists() todavía está en desuso, pero fs.existsSync()ya no está en desuso. Para que pueda usarlo con seguridad ahora.Puedes usar statSynco lstatSync( docs link ), que te da un fs.Statsobjeto . En general, si una versión síncrona de una función está disponible, tendrá el mismo nombre que la versión asíncrona con Syncal final. Así statSynces la versión sincrónica de stat; lstatSynces la versión sincrónica de lstat, etc.
lstatSync le informa a ambos si algo existe y, de ser así, si se trata de 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 si existe 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 que try/catch; arroja un error si la entrada no existe en absoluto.
Si no le importa lo que la entrada es y sólo quiere saber si es que existe, puede utilizar path.existsSync(o con la última, fs.existsSync) como se ha señalado por user618408 :
var path = require('path');
if (path.existsSync("/the/path")) { // or fs.existsSync
// ...
}
No requiere un try/catchpero no le da información sobre qué es la cosa, solo que está allí. path.existsSyncfue en desuso hace mucho tiempo.
Nota al margen: Usted ha preguntado expresamente cómo verificar sincrónicamente , por lo que he usado las xyzSyncversiones de las funciones anteriores. Pero siempre que sea posible, con E / S, lo mejor es evitar las llamadas sincrónicas. Las llamadas al subsistema de E / S toman un tiempo considerable desde el punto de vista de una CPU. Tenga en cuenta lo fácil que es llamar en lstatlugar de lstatSync:
// Is it a directory?
lstat('/the/path', function(err, stats) {
if (!err && stats.isDirectory()) {
// Yes it is
}
});
Pero si necesita la versión sincrónica, está ahí.
La siguiente respuesta de hace un par de años ahora está un poco desactualizada. La forma actual es usar fs.existsSyncpara hacer una verificación sincrónica de la existencia de un archivo / directorio (o, por supuesto, fs.existspara una verificación asincrónica), en lugar de las pathversiones a continuación.
Ejemplo:
var fs = require('fs');
if (fs.existsSync(path)) {
// Do something
}
// Or
fs.exists(path, function(exists) {
if (exists) {
// Do something
}
});
Y aquí estamos en 2015 y los documentos del Nodo ahora dicen que fs.existsSync(y fs.exists) "quedarán en desuso". (Debido a que la gente del Nodo 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.
No sé cuánto tiempo lleva allí, pero también hay 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 usar fs.accesspara hacer verificaciones de existencia ( " fs.access()Se recomienda verificar si un archivo existe sin manipularlo después " ). Pero tenga en cuenta que el acceso que no está disponible se considera un error , por lo que probablemente sea mejor si espera que el archivo sea accesible:
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
}
});
Puedes usar fs.existsSync():
if (fs.existsSync(path)) {
// Do something
}
Fue en desuso durante varios años, pero ya no lo es. De los documentos:
Tenga en cuenta que
fs.exists()está en desuso, perofs.existsSync()no lo está. (El parámetro de devolución de llamada parafs.exists()aceptar parámetros que son inconsistentes con otras devoluciones de llamada de Node.js.fs.existsSync()No utiliza una devolución de llamada).
openllamada y manejar la excepción o lo que sea si el archivo no fue encontró. Después de todo, el mundo real es caótico: si comprueba primero y está allí, eso no significa que seguirá estando allí cuando intente abrirlo; si verifica primero y no está allí, eso no significa que no estará allí un momento después. Momentos así parecen ser casos extremos, pero surgen todo el tiempo . Entonces, si va a abrir, no tiene sentido verificar primero.
Mirando la fuente, hay una versión sincrónica de path.exists- path.existsSync. Parece que se perdió en los documentos.
path.existsy path.existsSyncahora están en desuso . Por favor use .fs.existsyfs.existsSync
fs.exists y quedado en desuso . Utilice fs.stat () o fs.access () en su lugar.fs.existsSynctambién han
uso fs.existsSync. No está en desuso.
https://nodejs.org/api/fs.html#fs_fs_existssync_path
fs.existsSync.
existsfunción:is-there
fs.existscomo obsoletos mientras fs.existsSyncque no lo están!
Utilizando las API actualmente recomendadas (a partir de 2015) (según los documentos del nodo), esto es lo que hago:
var fs = require('fs');
function fileExists(filePath)
{
try
{
return fs.statSync(filePath).isFile();
}
catch (err)
{
return false;
}
}
En respuesta a la cuestión EPERM planteada 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 que el archivo existe o no, pero también puede obtener un error de permisos. El error de permisos no implica necesariamente que el archivo exista, porque es posible que no tenga permiso para el directorio que contiene el archivo en el que está comprobando. 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 necesitaría tener en cuenta un error EPERM, entre otras cosas).
Si bien la respuesta fs.existsSync aborda la pregunta que se hace aquí directamente, eso a menudo no va a ser lo que desea (no solo quiere saber si "algo" existe en un camino, probablemente le importe si la "cosa" 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 tomar alguna acción basada en el resultado, y esa lógica (la verificación y / o la acción posterior) debe acomodar 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.
file.exists()utilidad simple para el 3% y, en su lugar, ¿nos obligará a envolver esto en un intento de captura? Se real ... Perra del día.
Otra actualización
Al necesitar una respuesta para 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 de salida para detectar si un archivo no existe:
de los documentos:
fs.exists () es un anacronismo y existe solo por razones históricas. Casi nunca debería haber una razón para usarlo en su propio código.
En particular, verificar si existe un archivo antes de abrirlo es un antipatrón que lo deja vulnerable a las condiciones de carrera: otro proceso puede eliminar el archivo entre las llamadas a fs.exists () y fs.open (). Simplemente abra el archivo y maneje el error cuando no esté allí.
Yo uso la siguiente función para probar si existe el archivo. Captura también otras excepciones. Entonces, en caso de que haya problemas de derechos, por ejemplo, chmod ugo-rwx filenameo en la Right Click -> Properties -> Security -> Advanced -> Permission entries: empty list ..función de Windows
, se devuelve la excepción como debería. El archivo existe pero no tenemos derechos para acceder a él. Sería un error ignorar este tipo de excepciones.
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, ...
}
}
Salida de excepción, documentación de errores de nodejs en caso de que el archivo no exista:
{
[Error: ENOENT: no such file or directory, stat 'X:\\delsdfsdf.txt']
errno: -4058,
code: 'ENOENT',
syscall: 'stat',
path: 'X:\\delsdfsdf.txt'
}
Excepción en caso de que no tengamos derechos sobre el archivo, pero exista:
{
[Error: EPERM: operation not permitted, stat 'X:\file.txt']
errno: -4048,
code: 'EPERM',
syscall: 'stat',
path: 'X:\\file.txt'
}
fs.exists () está en desuso No lo use https://nodejs.org/api/fs.html#fs_fs_exists_path_callback
Puede implementar el modo core nodejs utilizado en esto: 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;
}
esto devolverá el objeto de estadísticas y, una vez que tenga el objeto de estadísticas, puede intentar
var exist = statPath('/path/to/your/file.js');
if(exist && exist.isFile()) {
// do something
}
Algunas respuestas aquí dicen eso fs.existsy fs.existsSyncambos están en desuso. Según los documentos, esto ya no es cierto. Solo fs.existsestá en desuso ahora:
Tenga en cuenta que fs.exists () está en desuso, pero fs.existsSync () no. (El parámetro de devolución de llamada a 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).
Por lo tanto, puede usar fs.existsSync () de forma segura para verificar sincrónicamente si existe un archivo.
El pathmódulo no proporciona una versión síncrona, por path.existslo que debe engañar con el fsmódulo.
Lo más rápido que puedo imaginar es usarlo, fs.realpathSynclo que arrojará un error que debe detectar, por lo que debe hacer que su propia función de contenedor con un try / catch.
El uso de las pruebas de fileSystem (fs) activará objetos de error, que luego deberá incluir en una declaración try / catch. Ahórrese un poco de esfuerzo y use una función introducida en la rama 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);
});
});
Los documentos sobre fs.stat()dice usar fs.access()si no vas a manipular el archivo. No dio una justificación, ¿podría ser un uso más rápido o menos memorable?
Yo uso el nodo para la automatización lineal, así que pensé en compartir la función que uso para probar la existencia del archivo.
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;
}
Respuestas actualizadas para aquellas personas que "correctamente" señalan que no responde directamente a la pregunta, más aportan una opción alternativa.
fs.existsSync('filePath')También vea los documentos aquí .
Devuelve verdadero si la ruta existe, falso de lo contrario.
En un contexto asíncrono, podría escribir la versión asíncrona en el método de sincronización con el uso de la awaitpalabra clave. Simplemente puede convertir el método de devolución de llamada asíncrono en una promesa como esta:
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');
}
}
los documentos sobre acceso ().
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); }, ); }); }
Lo más probable es que, si desea saber si existe un archivo, planea solicitarlo si es así.
function getFile(path){
try{
return require(path);
}catch(e){
return false;
}
}
Aquí hay una solución de envoltura simple para esto:
var fs = require('fs')
function getFileRealPath(s){
try {return fs.realpathSync(s);} catch(e){return false;}
}
Uso:
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);
}
Asegúrese de usar el operador === para probar si return es igual a falso. No hay una razón lógica para que fs.realpathSync () devuelva falso en condiciones de trabajo adecuadas, por lo que creo que esto debería funcionar al 100%.
Preferiría ver una solución que no genere un Error y el impacto en el rendimiento resultante. Desde una perspectiva API, fs.exists () parece la solución más elegante.
De las respuestas parece que no hay soporte oficial de API para esto (como en una verificación directa y explícita). Muchas de las respuestas dicen que use stat, sin embargo, no son estrictas. No podemos suponer, por ejemplo, que cualquier error arrojado por stat significa que algo no existe.
Digamos que lo intentamos con algo que no existe:
$ 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' }
Probémoslo con algo que existe pero al que no tenemos acceso:
$ 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' }
Por lo menos querrás:
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 pregunta no está clara sobre si realmente desea que sea sincrónico o si solo desea que se escriba como si fuera sincrónico. Este ejemplo usa wait / async para que solo se escriba sincrónicamente pero se ejecute de forma asíncrona.
Esto significa que debe llamarlo como tal en el nivel superior:
(async () => {
try {
console.log(await dir_exists('god'));
console.log(await dir_exists('fsm/appendage'));
}
catch(e) {
console.log(e);
}
})();
Una alternativa es usar .then y .catch en la promesa devuelta por la llamada asincrónica si la necesita más abajo.
Si desea verificar si algo existe, es una buena práctica asegurarse también de que es el tipo correcto de cosas, como un directorio o archivo. Esto está incluido en el ejemplo. Si no se permite que sea un enlace simbólico, debe usar lstat en lugar de stat, ya que stat atravesará automáticamente los enlaces.
Puede reemplazar todo el asíncrono para sincronizar el código aquí y usar statSync en su lugar. Sin embargo, espere que una vez que async y espere se vuelvan universalmente compatibles, las llamadas de Sync se volverán redundantes y eventualmente se depreciarán (de lo contrario, tendría que definirlas en todas partes y en la cadena al igual que con async, lo que lo hace realmente inútil).