O Node.js verifica se o caminho é arquivo ou diretório


380

Não consigo obter nenhum resultado de pesquisa que explique como fazer isso.

Tudo o que quero fazer é saber se um determinado caminho é um arquivo ou um diretório (pasta).

Respostas:


609

fs.lstatSync(path_string).isDirectory()deveria te contar. Dos documentos :

Os objetos retornados de fs.stat () e fs.lstat () são desse tipo.

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

NOTA:

A solução acima será throwum Errorif; por exemplo, o fileou directorynão existe.

Se você quer uma trueou falseabordagem, tente fs.existsSync(dirPath) && fs.lstatSync(dirPath).isDirectory();como mencionado por Joseph nos comentários abaixo.


18
Observe que a versão assíncrona geralmente é preferível se você se preocupa com o desempenho geral do aplicativo.
AlexMA #

45
Lembre-se de que, se o diretório ou arquivo não existir, você receberá um erro novamente.
Ethan Mick

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

Lembre-se de que, se o arquivo ou diretório não existir, será lançada uma exceção que precisa ser detectada, caso contrário, causará uma saída anormal.
Sergey Kuznetsov

59

Atualização: Node.Js> = 10

Podemos usar a nova API fs.promises

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

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

Qualquer versão do Node.Js

Veja como você detectaria se um caminho é um arquivo ou um diretório assincronamente , que é a abordagem recomendada no nó. 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()}`);
});

Observe ao usar a API síncrona:

Ao usar o formulário síncrono, quaisquer exceções são lançadas imediatamente. Você pode usar try / catch para lidar com exceções ou permitir que elas borbulhem.

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

Isso ainda é considerado experimental a partir de março de 2020? Onde podemos olhar para ver? - Opa, quando clico no link acima, vejo que agora ele está estável (o que implica em não ser mais experimental).
alfreema 9/03

20

Sério, a pergunta existe há cinco anos e nenhuma fachada agradável?

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

Dependendo de suas necessidades, você provavelmente pode confiar no pathmódulo do nó .

Você pode não conseguir acessar o sistema de arquivos (por exemplo, o arquivo ainda não foi criado) e provavelmente deseja evitar atingi-lo, a menos que realmente precise da validação extra. Se você puder supor que o que você está procurando segue o .<extname>formato, basta olhar para o nome.

Obviamente, se você estiver procurando por um arquivo sem um nome ext, precisará acessar o sistema de arquivos para ter certeza. Mas mantenha as coisas simples até que você precise de mais complicações.

const path = require('path');

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

2
Obviamente, isso não funcionará em todas as situações, mas é muito mais rápido e fácil do que as outras respostas, se você puder fazer as suposições necessárias.
Electrovir

1

As respostas acima verificam se um sistema de arquivos contém um caminho que é um arquivo ou diretório. Mas ele não identifica se um determinado caminho sozinho é um arquivo ou diretório.

A resposta é identificar caminhos baseados em diretório usando "/". como -> "/ c / dos / run /." <- período à direita.

Como um caminho de um diretório ou arquivo que ainda não foi gravado. Ou um caminho de um computador diferente. Ou um caminho em que existe um arquivo e um diretório com o mesmo 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);
}

Versão do nó: v11.10.0 - fev 2019

Último pensamento: por que acertar o sistema de arquivos?


1

Aqui está uma função que eu uso. Ninguém está usando promisifye await/asyncdestacado neste post, então pensei em compartilhar.

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: eu não uso require('fs').promises;porque já é experimental há um ano, é melhor não confiar nele.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.