web-dev-qa-db-fra.com

Node.js vérifie si le chemin est un fichier ou un répertoire

Je n'arrive pas à obtenir des résultats de recherche qui expliquent comment faire cela.

Tout ce que je veux faire, c'est savoir si un chemin donné est un fichier ou un répertoire (dossier).

329
ThomasReggi

fs.lstatSync(path_string).isDirectory() devrait vous le dire. De la docs :

Les objets renvoyés par fs.stat () et fs.lstat () sont de ce type.

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

NOTE: La solution ci-dessus va throw un Error if; par exemple, la file ou directory n'existe pas. Si vous voulez un truthy ou falsy essayez fs.existsSync(dirPath) && fs.lstatSync(dirPath).isDirectory(); comme mentionné par Joseph dans les commentaires ci-dessous.

523
Jason Sperske

Mise à jour: Node.Js> = 10

Nous pouvons utiliser la nouvelle fs.promises API

Expérimental Cette fonctionnalité est toujours en cours de développement et sous réserve de modifications non compatibles avec les versions antérieures, voire de suppression, dans les versions futures. L'utilisation de cette fonctionnalité n'est pas recommandée dans les environnements de production. Les fonctionnalités expérimentales ne sont pas soumises au modèle de versioning sémantique de Node.js.

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

(async() => {

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

N'importe quelle version de Node.Js

Voici comment vous pourriez détecter si un chemin est un fichier ou un répertoire de manière asynchrone , ce qui est l’approche recommandée dans le noeud. en utilisant 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()}`);
});

Remarque lors de l'utilisation de l'API synchrone:

Lorsque vous utilisez le formulaire synchrone, toutes les exceptions sont immédiatement levées. Vous pouvez utiliser try/catch pour gérer les exceptions ou leur permettre de faire des bulles.

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
   }
}
45
Marcos Casagrande

Sérieusement, la question existe cinq ans et pas de belle façade?

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

Selon vos besoins, vous pouvez probablement vous fier au module path du noeud.

Vous ne pourrez peut-être pas accéder au système de fichiers (par exemple, le fichier n’a pas encore été créé) et vous voudrez probablement éviter de toucher le système de fichiers, sauf si vous avez vraiment besoin de la validation supplémentaire. Si vous pouvez supposer que ce que vous vérifiez correspond au format .<extname>, regardez simplement le nom.

De toute évidence, si vous recherchez un fichier sans nom externe, vous devez utiliser le système de fichiers pour en être sûr. Mais restez simple jusqu'à ce que vous ayez besoin de plus de complication.

const path = require('path');

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

Les réponses ci-dessus vérifient si un système de fichiers contient un chemin qui est un fichier ou un répertoire. Mais il n'identifie pas si un seul chemin donné est un fichier ou un répertoire.

La solution consiste à identifier les chemins basés sur l'annuaire à l'aide de "/". comme -> "/ c/dos/run /." <- période de fuite.

Comme un chemin d'accès d'un répertoire ou d'un fichier qui n'a pas encore été écrit. Ou un chemin depuis un autre ordinateur. Ou un chemin d'accès où existent à la fois un fichier et un répertoire du même nom.

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

Version du nœud: v11.10.0 - fév 2019

Dernière pensée: Pourquoi même frapper le système de fichiers?

1
TamusJRoyce

Voici une fonction autonome que j'utilise dans certains de mes programmes. Personne ne fait usage de promisify et await/async dans ce post, j'ai donc pensé partager.

const isDirectory = async path => {
  try {
    return (await require('util').promisify(require('fs').lstat)(path)).isDirectory()
  } catch (e) {
    return false // or custom the error
  }
}

Note: Je n'utilise pas require('fs').promises; parce que c'est expérimental depuis un an, ne comptez pas dessus.

0
vdegenne