6

Node.js: Как проверить, является ли путь файлом или директорией?

11

Я не могу найти никаких результатов поиска, которые объясняли бы, как это сделать.

Мне нужно просто узнать, является ли данный путь файлом или директорией (папкой).

5 ответ(ов)

0

Вот функция, которую я использую. Никто не упомянул о promisify и особенностях async/await в этом посте, поэтому решил поделиться своим решением.

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

Примечание: Я не использую require('fs').promises, потому что это было экспериментально в течение года, и лучше не полагаться на это.

0

В зависимости от ваших потребностей, вы можете использовать модуль path в Node.js.

Возможно, вы не сможете взаимодействовать с файловой системой (например, файл ещё не создан), и, честно говоря, вам, вероятно, не стоит обращаться к файловой системе, если это не является абсолютно необходимым для дополнительной валидации. Если вы можете предположить, что то, что вы проверяете, соответствует формату .<extname>, просто посмотрите на имя.

Очевидно, что если вы ищете файл без расширения, вам нужно будет обратиться к файловой системе, чтобы быть уверенным. Но старайтесь делать всё просто, пока не потребуется что-то более сложное.

const path = require('path');

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

На StackOverflow.com действительно можно встретить вопросы, которые существуют уже несколько лет, и на которые до сих пор нет удобного решения. В вашем случае, код, который вы представили, выполняет проверку, является ли указанный путь директорией или нет, и он написан вполне корректно. Давайте разберем его подробнее.

Этот код использует метод lstatSync из модуля fs для получения метаданных о файле или каталоге. Ваша функция isDir принимает строку path и возвращает true, если указанный путь является директорией и false, если нет. Имейте в виду, что если путь не существует (например, вы проверяете несуществующий файл или каталог), то функция поймает ошибку и также вернет false.

Вот как выглядит ваша функция:

import {lstatSync} from 'fs';

/**
 * @param {string} path - Путь.
 * @returns {boolean} Является ли путь директорией, в противном случае всегда false.
 */
function isDir(path) {
  try {
    const stat = lstatSync(path);
    return stat.isDirectory();
  } catch (e) {
    // lstatSync выбрасывает ошибку, если путь не существует
    return false;
  }
}

Пример использования:

console.log("Is /tmp      a dir?", isDir("/tmp")      ? 'Yes!' : 'No!');
console.log("Is /root     a dir?", isDir("/root")     ? 'Yes!' : 'No!');
console.log("Is /dev      a dir?", isDir("/dev")      ? 'Yes!' : 'No!');
console.log("Is /dev/null a dir?", isDir("/dev/null") ? 'Yes!' : 'No!');

На Unix-подобной системе данный код выведет:

Is /tmp      a dir? Yes!
Is /root     a dir? Yes!
Is /dev      a dir? Yes!
Is /dev/null a dir? No!

С точки зрения "красивого интерфейса" (facade), можно было бы создать интерфейс для работы с файлами и директориями, который обеспечивал бы более удобный доступ к проверкам путей, а также обработку ошибок более читабельным образом. Однако предлагаемый вами подход вполне рабочий и эффективно выполняет поставленную задачу. Если у вас есть какие-либо предложения или идеи по улучшению текущего решения, это было бы замечательно!

0

Ответы выше проверяют, содержит ли файловая система путь, который является файлом или директорией, но не определяют, является ли данный путь самостоятельно файлом или директорией.

Ответ заключается в определении путей, основанных на директориях, с использованием "/." как, например, --> "/c/dos/run/." ←- с завершающей точкой.

Это подходит для случаев, когда путь к директории или файлу еще не записан, или когда путь из другой машины, или когда существует как файл, так и директория с одинаковым именем.

// /tmp/
// |- dozen.path
// |- dozen.path/.
//    |- eggs.txt
//
// "/tmp/dozen.path" !== "/tmp/dozen.path/"
//
// Очень немногие файловые системы допускают это. Но все же. Не доверяйте файловой системе на 100%!

// Конвертирует нестандартный "путь-оканчивается-слешом" в стандартный "путь-идентифицируется-символом текущей директории '.' или предыдущей '..'.
function tryGetPath(pathItem) {
    const isPosix = pathItem.includes("/");
    if ((isPosix && pathItem.endsWith("/")) ||
        (!isPosix && pathItem.endsWith("\\"))) {
        pathItem = pathItem + ".";
    }
    return pathItem;
}
// Если путь заканчивается на идентификатор текущей директории, значит, это путь! /c/dos/run/. и 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("\\.."));
} 
// Если путь не является директорией и не пустой, он должен быть файлом.
function isFile(pathItem) {
    if (pathItem === "") {
        return false;
    }
    return !isDirectory(pathItem);
}

Версия Node: v11.10.0 - февраль 2019

Последняя мысль: Зачем вообще обращаться к файловой системе?

0

Node 20+ ESM

Это версия ответа @Jason с использованием ESM

import { lstatSync } from 'node:fs'; 

export const isDirectory = (path) => lstatSync(path) ? lstatSync(path).isDirectory() : false;

Если по указанному пути нет директории или файла, lstatSync выбросит ошибку с текстом no such file or directory.

Чтобы избежать этой ошибки, вы можете использовать блок try...catch:

import { lstatSync } from 'node:fs'; 

export const isDirectory = (path) => {
    try {
        return lstatSync(path).isDirectory();
    } catch (error) {
        if (error.code === 'ENOENT') {
            return false; // Путь не существует
        }
        throw error; // Пробрасываем другие ошибки
    }
};

Таким образом, функция будет корректно обрабатывать отсутствие файла или директории и вернет false, вместо того чтобы выбрасывать ошибку.

Чтобы ответить на вопрос, пожалуйста, войдите или зарегистрируйтесь