Node.js: Как проверить, является ли путь файлом или директорией?
Я не могу найти никаких результатов поиска, которые объясняли бы, как это сделать.
Мне нужно просто узнать, является ли данный путь файлом или директорией (папкой).
5 ответ(ов)
Вот функция, которую я использую. Никто не упомянул о 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
, потому что это было экспериментально в течение года, и лучше не полагаться на это.
В зависимости от ваших потребностей, вы можете использовать модуль path
в Node.js.
Возможно, вы не сможете взаимодействовать с файловой системой (например, файл ещё не создан), и, честно говоря, вам, вероятно, не стоит обращаться к файловой системе, если это не является абсолютно необходимым для дополнительной валидации. Если вы можете предположить, что то, что вы проверяете, соответствует формату .<extname>
, просто посмотрите на имя.
Очевидно, что если вы ищете файл без расширения, вам нужно будет обратиться к файловой системе, чтобы быть уверенным. Но старайтесь делать всё просто, пока не потребуется что-то более сложное.
const path = require('path');
function isFile(pathItem) {
return !!path.extname(pathItem);
}
На 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), можно было бы создать интерфейс для работы с файлами и директориями, который обеспечивал бы более удобный доступ к проверкам путей, а также обработку ошибок более читабельным образом. Однако предлагаемый вами подход вполне рабочий и эффективно выполняет поставленную задачу. Если у вас есть какие-либо предложения или идеи по улучшению текущего решения, это было бы замечательно!
Ответы выше проверяют, содержит ли файловая система путь, который является файлом или директорией, но не определяют, является ли данный путь самостоятельно файлом или директорией.
Ответ заключается в определении путей, основанных на директориях, с использованием "/." как, например, --> "/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
Последняя мысль: Зачем вообще обращаться к файловой системе?
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
, вместо того чтобы выбрасывать ошибку.
Как создать каталог и все отсутствующие родительские каталоги?
Запись в файлы в Node.js
Как использовать для поиска файлов рекурсивно?
Как добавить данные в файл в Node?
Как скачать файл с помощью Node.js (без использования сторонних библиотек)?