Node.js comprueba si la ruta es un archivo o directorio

381

Parece que no puedo obtener ningún resultado de búsqueda que explique cómo hacer esto.

Todo lo que quiero hacer es saber si una ruta determinada es un archivo o un directorio (carpeta).

ThomasReggi
fuente

Respuestas:

610

fs.lstatSync(path_string).isDirectory()debería decirte De los documentos :

Los objetos devueltos por fs.stat () y fs.lstat () son de este tipo.

stats.isFile()
stats.isDirectory()
stats.isBlockDevice()
stats.isCharacterDevice()
stats.isSymbolicLink() (only valid with fs.lstat())
stats.isFIFO()
stats.isSocket()

NOTA:

La solución anterior será throwun Errorif; por ejemplo, el fileo directoryno existe.

Si quieres una trueo falseenfoque, tratar fs.existsSync(dirPath) && fs.lstatSync(dirPath).isDirectory();como se ha mencionado por José en los comentarios a continuación.

Jason Sperske
fuente
18
Tenga en cuenta que la versión asincrónica generalmente es preferible si le preocupa el rendimiento general de la aplicación.
AlexMA
45
Tenga en cuenta que si el directorio o el archivo no existe, recibirá un error.
Ethan Mick
99
let isDirExists = fs.existsSync(dirPath) && fs.lstatSync(dirPath).isDirectory();
Jossef Harush
Tenga en cuenta que si el archivo o directorio no existe, generará una excepción que debe detectarse; de ​​lo contrario, provocará una salida anormal.
Sergey Kuznetsov
59

Actualización: Node.Js> = 10

Podemos usar la nueva API fs.promises

const fs = require('fs').promises;

(async() => {
    const stat = await fs.lstat('test.txt');
    console.log(stat.isFile());
})().catch(console.error)

Cualquier versión de Node.Js

Así es como detectaría si una ruta es un archivo o un directorio de forma asincrónica , que es el enfoque recomendado en el nodo. usando fs.lstat

const fs = require("fs");

let path = "/path/to/something";

fs.lstat(path, (err, stats) => {

    if(err)
        return console.log(err); //Handle error

    console.log(`Is file: ${stats.isFile()}`);
    console.log(`Is directory: ${stats.isDirectory()}`);
    console.log(`Is symbolic link: ${stats.isSymbolicLink()}`);
    console.log(`Is FIFO: ${stats.isFIFO()}`);
    console.log(`Is socket: ${stats.isSocket()}`);
    console.log(`Is character device: ${stats.isCharacterDevice()}`);
    console.log(`Is block device: ${stats.isBlockDevice()}`);
});

Tenga en cuenta al usar la API síncrona:

Cuando se usa la forma síncrona, cualquier excepción se produce inmediatamente. Puede usar try / catch para manejar excepciones o permitir que surjan.

try{
     fs.lstatSync("/some/path").isDirectory()
}catch(e){
   // Handle error
   if(e.code == 'ENOENT'){
     //no such file or directory
     //do something
   }else {
     //do something else
   }
}
Marcos Casagrande
fuente
¿Esto todavía se considera experimental a partir de marzo de 2020? ¿Dónde podemos mirar para ver? - Vaya, cuando hago clic en el enlace de arriba, ahora es estable (lo que implica que ya no es experimental).
Alfreema
20

En serio, la pregunta existe cinco años y no hay bonita fachada?

function is_dir(path) {
    try {
        var stat = fs.lstatSync(path);
        return stat.isDirectory();
    } catch (e) {
        // lstatSync throws an error if path doesn't exist
        return false;
    }
}
lama12345
fuente
14

Dependiendo de sus necesidades, probablemente pueda confiar en el pathmódulo del nodo .

Es posible que no pueda acceder al sistema de archivos (por ejemplo, el archivo aún no se ha creado) y, por cierto, es probable que desee evitar presionar el sistema de archivos a menos que realmente necesite la validación adicional. Si puede suponer que lo que está buscando sigue el .<extname>formato, solo mire el nombre.

Obviamente, si está buscando un archivo sin un nombre de extensión, deberá acceder al sistema de archivos para estar seguro. Pero manténgalo simple hasta que necesite más complicado.

const path = require('path');

function isFile(pathItem) {
  return !!path.extname(pathItem);
}
cndw
fuente
2
Obviamente, esto no funcionará en todas las situaciones, pero es mucho más rápido y fácil que las otras respuestas si puede hacer las suposiciones necesarias.
electrovir
1

Las respuestas anteriores verifican si un sistema de archivos contiene una ruta que es un archivo o directorio. Pero no identifica si una ruta dada solo es un archivo o directorio.

La respuesta es identificar rutas basadas en directorios usando "/". como -> "/ c / dos / run /". <- período final.

Como una ruta de un directorio o archivo que aún no se ha escrito. O un camino desde una computadora diferente. O una ruta donde existe tanto un archivo como un directorio con el mismo nombre.

// /tmp/
// |- dozen.path
// |- dozen.path/.
//    |- eggs.txt
//
// "/tmp/dozen.path" !== "/tmp/dozen.path/"
//
// Very few fs allow this. But still. Don't trust the filesystem alone!

// Converts the non-standard "path-ends-in-slash" to the standard "path-is-identified-by current "." or previous ".." directory symbol.
function tryGetPath(pathItem) {
    const isPosix = pathItem.includes("/");
    if ((isPosix && pathItem.endsWith("/")) ||
        (!isPosix && pathItem.endsWith("\\"))) {
        pathItem = pathItem + ".";
    }
    return pathItem;
}
// If a path ends with a current directory identifier, it is a path! /c/dos/run/. and c:\dos\run\.
function isDirectory(pathItem) {
    const isPosix = pathItem.includes("/");
    if (pathItem === "." || pathItem ==- "..") {
        pathItem = (isPosix ? "./" : ".\\") + pathItem;
    }
    return (isPosix ? pathItem.endsWith("/.") || pathItem.endsWith("/..") : pathItem.endsWith("\\.") || pathItem.endsWith("\\.."));
} 
// If a path is not a directory, and it isn't empty, it must be a file
function isFile(pathItem) {
    if (pathItem === "") {
        return false;
    }
    return !isDirectory(pathItem);
}

Versión de nodo: v11.10.0 - febrero de 2019

Último pensamiento: ¿Por qué incluso golpear el sistema de archivos?

TamusJRoyce
fuente
1

Aquí hay una función que uso. Nadie está haciendo uso de promisifyy la await/asyncfunción en este post, así que pensé que iba a compartir.

const promisify = require('util').promisify;
const lstat = promisify(require('fs').lstat);

async function isDirectory (path) {
  try {
    return (await lstat(path)).isDirectory();
  }
  catch (e) {
    return false;
  }
}

Nota: No lo uso require('fs').promises;porque ha sido experimental durante un año, mejor no confíe en él.

vdegenne
fuente