Node.js controlla se il percorso è il file o la directory


381

Non riesco a ottenere risultati di ricerca che spieghino come farlo.

Tutto quello che voglio fare è sapere se un determinato percorso è un file o una directory (cartella).

Risposte:


610

fs.lstatSync(path_string).isDirectory()dovrei dirtelo. Dai documenti :

Gli oggetti restituiti da fs.stat () e fs.lstat () sono di questo tipo.

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

NOTA:

La soluzione di cui sopra sarà throwun Errorif; per esempio, il fileo directorynon esiste.

Se vuoi un approccio trueo false, prova fs.existsSync(dirPath) && fs.lstatSync(dirPath).isDirectory();come indicato da Joseph nei commenti qui sotto.


18
Nota che la versione asincrona è generalmente preferibile se ti preoccupi delle prestazioni generali dell'app.
AlexMA

45
Tieni presente che se la directory o il file non esiste, verrà visualizzato un errore.
Ethan Mick,

9
let isDirExists = fs.existsSync(dirPath) && fs.lstatSync(dirPath).isDirectory();
Jossef Harush,

Tieni presente che se il file o la directory non esiste genererà un'eccezione che deve essere rilevata altrimenti causerà un'uscita anomala.
Sergey Kuznetsov,

59

Aggiornamento: Node.Js> = 10

Possiamo usare la nuova API fs.promises

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

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

Qualsiasi versione di Node.Js

Ecco come rilevare se un percorso è un file o una directory in modo asincrono , che è l'approccio consigliato nel 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()}`);
});

Nota quando si utilizza l'API sincrona:

Quando si utilizza la forma sincrona, vengono immediatamente emesse eccezioni. È possibile utilizzare try / catch per gestire le eccezioni o consentire loro di eseguire il bubble up.

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

Questo è ancora considerato sperimentale a partire da marzo 2020? Dove possiamo guardare per vedere? - Spiacenti, quando faccio clic sul link sopra, vedo che ora è stabile (il che implica che non è più sperimentale).
Alfreema,

20

Seriamente, la domanda esiste da cinque anni e nessuna bella facciata?

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

14

A seconda delle esigenze, è possibile fare affidamento sul pathmodulo del nodo .

Potresti non essere in grado di colpire il filesystem (ad es. Il file non è stato ancora creato) e tbh probabilmente vorrai evitare di colpire il filesystem a meno che tu non abbia davvero bisogno della convalida aggiuntiva. Se riesci a dare per scontato che ciò che stai controllando segua il .<extname>formato, basta guardare il nome.

Ovviamente se stai cercando un file senza un extname dovrai essere sicuro di colpire il filesystem. Ma mantienilo semplice fino a quando non avrai bisogno di più complicato.

const path = require('path');

function isFile(pathItem) {
  return !!path.extname(pathItem);
}

2
Ovviamente questo non funzionerà in tutte le situazioni, ma è molto più veloce e più facile rispetto alle altre risposte se puoi fare i presupposti necessari.
electrovir

1

Le risposte sopra verificano se un filesystem contiene un percorso che è un file o una directory. Ma non identifica se un determinato percorso da solo è un file o una directory.

La risposta è identificare i percorsi basati su directory usando "/." come -> "/ c / dos / run /." <- periodo finale.

Come un percorso di una directory o file che non è stato ancora scritto. O un percorso da un altro computer. O un percorso in cui esistono sia un file che una directory con lo stesso nome.

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

Versione nodo: v11.10.0 - Febbraio 2019

Ultimo pensiero: perché anche colpire il filesystem?


1

Ecco una funzione che uso. Nessuno fa uso promisifye await/asyncfunzionalità di questo post, quindi ho pensato di condividere.

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: non lo uso require('fs').promises;perché è stato sperimentale per un anno ormai, meglio non fare affidamento su di esso.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.