Compruebe sincrónicamente si el archivo/directorio existe en Node.js
(13)
Async Promise la solución (bluebirdjs)
Para aquellos que usan bluebirdjs y nodejs 7. La mejor manera de devolver una promesa booleana:
function fileExists(path){
return fs.accessAsync(path, fs.constants.F_OK) //F_OK checks if file is visible, is default does no need to be specified.
.then(err => !err);
}
los documentos: fs.access
¿Cómo puedo verificar sincrónicamente, utilizando node.js , si existe un archivo o directorio?
Algunas respuestas aquí dicen que fs.exists
y fs.existsSync
están en desuso. Según los documentos esto no es más cierto. Sólo fs.exists
está desprotegido ahora:
Tenga en cuenta que fs.exists () está en desuso, pero fs.existsSync () no está en desuso. (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() forma segura para verificar de forma síncrona si existe un archivo.
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:
- Funciona tanto para directorios como para archivos.
- Si el elemento existe, devuelve la ruta al archivo o directorio
- Si el artículo no existe, devuelve falso.
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 el retorno 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 debería funcionar al 100%.
Preferiría ver una solución que no genere un error y el impacto resultante en el rendimiento. Desde la perspectiva de la API, fs.exists () parece ser la solución más elegante.
De las respuestas, parece que no hay soporte oficial de API para esto (como en una comprobación directa y explícita). Muchas de las respuestas dicen usar stat, sin embargo no son estrictas. No podemos asumir, por ejemplo, que cualquier error arrojado por estadística 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'' }
Vamos a intentarlo con algo que existe pero que no tenemos acceso a:
$ 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'' }
Como mínimo 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 si realmente quiere que esté sincronizada o si solo quiere que se escriba como si estuviera sincronizada. Este ejemplo utiliza await / async para que solo se escriba de forma sincronizada pero se ejecute de forma asíncrona.
Esto significa que tienes que 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 de la llamada asíncrona si la necesita más abajo.
Si desea comprobar si algo existe, es una buena práctica asegurarse también de que es el tipo correcto de cosas, como un directorio o un archivo. Esto se incluye 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 código async para sincronizar aquí y usar statSync en su lugar. Sin embargo, espere que una vez que async y wait se conviertan en soporte universal, las llamadas Sync se vuelvan redundantes y se deprecien (de lo contrario, tendría que definirlas en todas partes y en la cadena como con async, lo que hace que sea realmente inútil).
El módulo de path
no proporciona una versión síncrona de path.exists
por lo que tiene que hacer trucos con el módulo fs
.
Lo más rápido que puedo imaginar es usar fs.realpathSync
que arrojará un error que debe detectar, por lo que debe crear su propia función de envoltorio con un try / catch.
El uso de las pruebas de fileSystem (fs) generará objetos de error, que luego deberá ajustar en una declaración try / catch. Ahórrese un poco de esfuerzo y use una característica que se presenta 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);
});
});
En cuanto a la fuente, hay una versión síncrona de path.exists
- path.existsSync
. Parece que se perdió en los documentos.
Actualizar:
path.exists
y path.existsSync
ahora están en desuso . Utilice . fs.exists
y fs.existsSync
Actualización 2016:
fs.exists
y fs.existsSync
también han quedado en desuso . Utilice fs.stat() o fs.access() lugar.
La respuesta a esta pregunta ha cambiado con los años. La respuesta actual está aquí en la parte superior, seguida de las diversas respuestas a lo largo de los años en orden cronológico:
Respuesta actual
Puedes usar fs.existsSync()
:
var fs = require(''fs'');
if (fs.existsSync(path)) {
// Do something
}
Estuvo en desuso durante varios años, pero ya no está. De la documentación:
Tenga en cuenta que
fs.exists()
está en desuso, perofs.existsSync()
no está en desuso. (El parámetro de devolución de llamada afs.exists()
acepta parámetros que son inconsistentes con otras devoluciones de llamada de Node.js.fs.existsSync()
no utiliza una devolución de llamada).
Específicamente, solicitó una verificación sincrónica , pero si puede usar una verificación asíncrona en su lugar (generalmente es mejor con E / S), use fs.access
(ya que exists
está en desuso).
Respuestas historicas
Aquí están las respuestas históricas en orden cronológico:
- Respuesta original del 2010.
(stat
/statSync
olstat
/lstatSync
) - Actualización septiembre 2012
(exists
/existsSync
) - Actualización febrero 2015
(Notando la inminente desaprobación deexists
/existsSync
, por lo que probablemente volvamos astat
/statSync
olstat
/lstatSync
) - Actualización diciembre 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; docs forfs.stat
recomienda usarfs.access
si necesita verificar la existencia sin abrir) - Actualización diciembre 2016
fs.exists()
todavía está en desuso perofs.existsSync()
ya no está en desuso. Así que puedes usarlo con seguridad ahora.
Respuesta original del 2010:
Puede usar statSync
o lstatSync
( docs link ), que le dan un objeto fs.Stats
. 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 Sync
al final. Así que statSync
es la versión síncrona de stat
; lstatSync
es la versión síncrona de lstat
, etc.
lstatSync
le informa si existe algo y, si es 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 es 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 un dispositivo de isBlockDevice
, etc., etc. Tenga en cuenta el try/catch
; arroja un error si la entrada no existe en absoluto.
Si no le importa qué es la entrada y solo quiere saber si existe, puede usar path.existsSync
(o con la última fs.existsSync
, 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 da información sobre qué es la cosa, solo que está ahí. path.existsSync
fue desaprobado hace mucho tiempo.
Nota al xyzSync
: ha preguntado expresamente cómo verificar de forma sincrónica , por lo que he usado las versiones xyzSync
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 mucho tiempo desde el punto de vista de la CPU. Tenga en cuenta lo fácil que es llamar a lstat
lugar de a lstatSync
:
// Is it a directory?
lstat(''/the/path'', function(err, stats) {
if (!err && stats.isDirectory()) {
// Yes it is
}
});
Pero si necesitas la versión síncrona, está ahí.
Actualización septiembre 2012
La siguiente respuesta de hace un par de años está ahora un poco desactualizada. La forma actual es usar fs.existsSync() para realizar una comprobación síncrona de la existencia del archivo / directorio (o, por supuesto, fs.exists
para una comprobación asíncrona), en lugar de las versiones de path
continuación.
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án en desuso". (Debido a que la gente de Node piensa que es tonto verificar si existe algo antes de abrirlo, lo que es; ¡pero esa no es la única razón para verificar si existe algo!)
Así que probablemente volvamos a los diversos métodos de stat
... Hasta / a menos que esto cambie una vez más, por supuesto.
Actualización diciembre 2015
No sé cuánto tiempo ha estado allí, pero también hay fs.access . Y al menos a partir de octubre de 2016, la documentación de fs.stat
recomienda usar fs.access
para realizar verificaciones de existencia ( "Para verificar si un archivo existe sin manipularlo posteriormente, se recomienda fs.access()
" ). Pero tenga en cuenta que el acceso que no está disponible se considera un error , por lo que probablemente sería mejor si está esperando 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
}
});
Actualización diciembre 2016
Puedes usar fs.existsSync()
:
if (fs.existsSync(path)) {
// Do something
}
Estuvo en desuso durante varios años, pero ya no está. De la documentación:
Tenga en cuenta que
fs.exists()
está en desuso, perofs.existsSync()
no está en desuso. (El parámetro de devolución de llamada afs.exists()
acepta parámetros que son inconsistentes con otras devoluciones de llamada de Node.js.fs.existsSync()
no utiliza una devolución de llamada).
Los documentos en fs.stat()
dicen usar fs.access()
si no va a manipular el archivo. No dio una justificación, ¿podría ser más rápido o menos uso de memoria?
Utilizo el nodo para la automatización lineal, así que pensé que comparto la función que uso para probar la existencia de archivos.
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;
}
Usando las API actualmente recomendadas (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 a la cuestión EPERM planteada por @broadband en los comentarios, se destaca un buen punto. fileExists () probablemente no sea una buena manera de pensar sobre esto en muchos casos, porque fileExists () no puede realmente prometer un retorno booleano. Es posible que pueda determinar definitivamente que el archivo existe o no existe, pero también puede obtener un error de permisos. El error de permisos no implica necesariamente que el archivo exista, ya que podría carecer de permiso 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.
Por lo tanto, mi código de arriba es realmente doesFileExistAndDoIHaveAccessToIt (), pero su pregunta podría ser doesfileNotExistAndCouldICreateIt (), que sería una lógica completamente diferente (que debería tener en cuenta un error EPERM, entre otras cosas).
Si bien la respuesta de fs.existsSync aborda la pregunta que se hace aquí directamente, a menudo no va a ser lo que desea (no solo quiere saber si "algo" existe en un camino, probablemente le preocupa 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 realizar alguna acción basada en el resultado, y esa lógica (la verificación y / o la acción subsiguiente) debe adaptarse a la idea que una cosa encontrada en esa ruta puede ser un archivo o un directorio, y que puede encontrar EPERM u otros errores en el proceso de verificación.
Yo uso la siguiente función para probar si el archivo existe. Atrapa también otras excepciones. Entonces, en caso de que haya problemas de derechos, por ejemplo, chmod ugo-rwx filename
o en Windows, Right Click -> Properties -> Security -> Advanced -> Permission entries: empty list ..
chmod ugo-rwx filename
Right Click -> Properties -> Security -> Advanced -> Permission entries: empty list ..
función devuelve la excepción como debería. El archivo existe pero no tenemos derechos de acceso. 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 existe:
{
[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 la forma de nodejs central utilizada en este: 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 que podría probar
var exist = statPath(''/path/to/your/file.js'');
if(exist && exist.isFile()) {
// do something
}
Otra actualización
Necesitando una respuesta a esta pregunta, busqué en 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 () 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 (). Solo abre el archivo y maneja el error cuando no esté allí.