Как проверить наличие файла?
В документации к модулю fs
есть описание метода fs.exists(path, callback)
. Но, как я понимаю, он проверяет наличие только каталогов. И мне нужно проверить файл!
Как это может быть сделано?
Как проверить наличие файла?
В документации к модулю fs
есть описание метода fs.exists(path, callback)
. Но, как я понимаю, он проверяет наличие только каталогов. И мне нужно проверить файл!
Как это может быть сделано?
Почему бы просто не попробовать открыть файл? fs.open('YourFile', 'a', function (err, fd) { ... })
в любом случае после минутного поиска попробуйте это:
var path = require('path');
path.exists('foo.txt', function(exists) {
if (exists) {
// do something
}
});
// or
if (path.existsSync('foo.txt')) {
// do something
}
Для Node.js v0.12.x и выше
Оба path.exists
и fs.exists
устарели
*Редактировать:
Изменено: else if(err.code == 'ENOENT')
to: else if(err.code === 'ENOENT')
Линтер жалуется на то, что двойное равенство не является тройным.
Использование fs.stat:
fs.stat('foo.txt', function(err, stat) {
if(err == null) {
console.log('File exists');
} else if(err.code === 'ENOENT') {
// file does not exist
fs.writeFile('log.txt', 'Some log\n');
} else {
console.log('Some other error: ', err.code);
}
});
fs.exists
тоже работает. У меня были проблемы с правами доступа к файлу.
- person RomanGorbatko; 17.07.2013
path.exists
на самом деле устарел в пользу fs.exists
- person Arnaud Rinquin; 26.05.2014
fs.exists
и fs.existsSync
также устарели. Лучший способ проверить наличие файла — fs.stat
, как показано выше.
- person Antrikshy; 29.03.2015
fs.existsSync
больше не устаревает, хотя fs.exists
все еще есть.
- person RyanZim; 12.10.2017
nodejs fs documentation
только говорит, что fs.exists
устарел, но что fs.existsSync
в порядке ???
- person oldboy; 03.01.2020
exists()
тип API отвечает на вопрос напрямую и может использоваться непосредственно в условии.
- person Szczepan Hołyszewski; 04.01.2021
Изменить: Поскольку узел v10.0.0
мы можем использовать fs.promises.access(...)
Пример асинхронного кода, который проверяет, существует ли файл:
function checkFileExists(file) {
return fs.promises.access(file, fs.constants.F_OK)
.then(() => true)
.catch(() => false)
}
Альтернативой статистике может быть использование нового fs.access(...)
:
минимизированная функция короткого обещания для проверки:
s => new Promise(r=>fs.access(s, fs.constants.F_OK, e => r(!e)))
Пример использования:
let checkFileExists = s => new Promise(r=>fs.access(s, fs.constants.F_OK, e => r(!e)))
checkFileExists("Some File Location")
.then(bool => console.log(´file exists: ${bool}´))
расширенный способ обещания:
// returns a promise which resolves true if file exists:
function checkFileExists(filepath){
return new Promise((resolve, reject) => {
fs.access(filepath, fs.constants.F_OK, error => {
resolve(!error);
});
});
}
или если вы хотите сделать это синхронно:
function checkFileExistsSync(filepath){
let flag = true;
try{
fs.accessSync(filepath, fs.constants.F_OK);
}catch(e){
flag = false;
}
return flag;
}
fs.constants.F_OK
и т. д. Можно ли также получить к ним доступ как fs.F_OK
? Странный. К тому же лаконичный, что приятно.
- person samson; 20.04.2018
fs.promises.access(path, fs.constants.F_OK);
, чтобы просто сделать обещание вместо создания обещания.
- person Jeremy Trpka; 20.06.2020
!(await fs.stat(path).catch(() => false))
существует: !!(await fs.stat(path).catch(() => false))
- person antitoxic; 26.08.2020
fs.exists
... действительно интересно, почему они заставляют нас использовать такие альтернативы :'-(
- person GLAND_PROPRE; 20.06.2021
Более простой способ сделать это синхронно.
if (fs.existsSync('/etc/file')) {
console.log('Found file');
}
В документе API описано, как работает existsSync
:
Проверьте, существует ли указанный путь, сверившись с файловой системой.
fs.existsSync
устарел, но больше не является.
- person RyanZim; 12.10.2017
Современный способ async/await (Node 12.8.x)
const fileExists = async path => !!(await fs.promises.stat(path).catch(e => false));
const main = async () => {
console.log(await fileExists('/path/myfile.txt'));
}
main();
Нам нужно использовать fs.stat() or fs.access()
, потому что fs.exists(path, callback)
теперь устарело
Еще один хороший способ — fs-extra.
const fileExists = path => fs.promises.stat(path).then(() => true, () => false);
- person ggorlen; 22.07.2021
fs.exists(path, callback)
и fs.existsSync(path)
теперь устарели, см. https://nodejs.org/api/fs.html#fs_fs_exists_path_callback и https://nodejs.org/api/fs.html#fs_fs_existssync_path.
Чтобы синхронно проверить существование файла, можно использовать ie. fs.statSync(path)
. Если файл существует, будет возвращен объект fs.Stats
, см. https://nodejs.org/api/fs.html#fs_class_fs_stats, в противном случае будет выдана ошибка, которая будет перехвачена оператором try/catch.
var fs = require('fs'),
path = '/path/to/my/file',
stats;
try {
stats = fs.statSync(path);
console.log("File exists.");
}
catch (e) {
console.log("File does not exist.");
}
fs
- person Dmitry Koroliov; 21.06.2017
fs.existsSync()
больше не считается устаревшим.
- person RyanZim; 12.10.2017
Старая версия до V6: здесь документация
const fs = require('fs');
fs.exists('/etc/passwd', (exists) => {
console.log(exists ? 'it\'s there' : 'no passwd!');
});
// or Sync
if (fs.existsSync('/etc/passwd')) {
console.log('it\'s there');
}
ОБНОВЛЕНИЕ
Новые версии V6: документация для fs.stat
fs.stat('/etc/passwd', function(err, stat) {
if(err == null) {
//Exist
} else if(err.code == 'ENOENT') {
// NO exist
}
});
fs.exists
, и fs.existsSync
устарели в соответствии со ссылкой, которой вы поделились.
- person Andy; 12.09.2016
existsSync
не считается устаревшим в соответствии с этим документом, возможно, так было, когда вы его читали.
- person Darpan; 12.04.2018
@Fox: отличный ответ! Вот небольшое расширение с некоторыми дополнительными опциями. Это то, что я использовал в последнее время в качестве решения:
var fs = require('fs');
fs.lstat( targetPath, function (err, inodeStatus) {
if (err) {
// file does not exist-
if (err.code === 'ENOENT' ) {
console.log('No file or directory at',targetPath);
return;
}
// miscellaneous error (e.g. permissions)
console.error(err);
return;
}
// Check if this is a file or directory
var isDirectory = inodeStatus.isDirectory();
// Get file size
//
// NOTE: this won't work recursively for directories-- see:
// http://stackoverflow.com/a/7550430/486547
//
var sizeInBytes = inodeStatus.size;
console.log(
(isDirectory ? 'Folder' : 'File'),
'at',targetPath,
'is',sizeInBytes,'bytes.'
);
}
P.S. проверьте fs-extra, если вы еще не используете его - это довольно мило. https://github.com/jprichardson/node-fs-extra)
fs.exists
устарел с версии 1.0.0. Вместо этого вы можете использовать fs.stat
.
var fs = require('fs');
fs.stat(path, (err, stats) => {
if ( !stats.isFile(filename) ) { // do this
}
else { // do this
}});
Вот ссылка на документацию fs.stats
stats.isFile()
не нужен filename
.
- person Wtower; 27.09.2016
Есть много неточных комментариев о том, что fs.existsSync()
устарело; Нет.
https://nodejs.org/api/fs.html#fs_fs_existssync_path
Обратите внимание, что fs.exists() устарела, а fs.existsSync() — нет.
async/await
версия с использованием util.promisify
с узла 8:
const fs = require('fs');
const { promisify } = require('util');
const stat = promisify(fs.stat);
describe('async stat', () => {
it('should not throw if file does exist', async () => {
try {
const stats = await stat(path.join('path', 'to', 'existingfile.txt'));
assert.notEqual(stats, null);
} catch (err) {
// shouldn't happen
}
});
});
describe('async stat', () => {
it('should throw if file does not exist', async () => {
try {
const stats = await stat(path.join('path', 'to', 'not', 'existingfile.txt'));
} catch (err) {
assert.notEqual(err, null);
}
});
});
После небольшого эксперимента я обнаружил, что следующий пример с использованием fs.stat
является хорошим способом асинхронной проверки существования файла. Он также проверяет, что ваш «файл» является «действительно файлом» (а не каталогом).
Этот метод использует обещания, предполагая, что вы работаете с асинхронной кодовой базой:
const fileExists = path => {
return new Promise((resolve, reject) => {
try {
fs.stat(path, (error, file) => {
if (!error && file.isFile()) {
return resolve(true);
}
if (error && error.code === 'ENOENT') {
return resolve(false);
}
});
} catch (err) {
reject(err);
}
});
};
Если файл не существует, промис все равно разрешается, хотя и false
. Если файл существует и является каталогом, то он разрешает true
. Любые ошибки при попытке прочитать файл будут reject
обещать саму ошибку.
Ну, я сделал это так, как показано на https://nodejs.org/api/fs.html#fs_fs_access_path_mode_callback
fs.access('./settings', fs.constants.F_OK | fs.constants.R_OK | fs.constants.W_OK, function(err){
console.log(err ? 'no access or dir doesnt exist' : 'R/W ok');
if(err && err.code === 'ENOENT'){
fs.mkdir('settings');
}
});
Есть ли какие-либо проблемы с этим?
в старые времена, прежде чем сесть, я всегда проверяю, есть ли стул, а потом сажусь, иначе у меня есть альтернативный план, например, сесть в карету. Теперь сайт node.js предлагает просто пойти (не нужно проверять), и ответ выглядит так:
fs.readFile( '/foo.txt', function( err, data )
{
if(err)
{
if( err.code === 'ENOENT' )
{
console.log( 'File Doesn\'t Exist' );
return;
}
if( err.code === 'EACCES' )
{
console.log( 'No Permission' );
return;
}
console.log( 'Unknown Error' );
return;
}
console.log( data );
} );
код взят с http://fredkschott.com/post/2014/03/understanding-error-first-callbacks-in-node-js/ от марта 2014 года и немного изменен для соответствия требованиям компьютера. Он также проверяет наличие разрешения — удалите разрешение для проверки chmod a-r foo.txt
function fileExists(path, cb){
return fs.access(path, fs.constants.F_OK,(er, result)=> cb(!err && result)) //F_OK checks if file is visible, is default does no need to be specified.
}
документы говорят, что вы должны использовать access()
в качестве замены устаревшему exists()
function fileExists(path, cb){
return new Promise((accept,deny) =>
fs.access(path, fs.constants.F_OK,(er, result)=> cb(!err && result))
);
}
var fs = require('fs-extra')
await fs.pathExists(filepath)
Как видите намного проще. И преимущество перед promisify в том, что с этим пакетом у вас есть полный набор текста (полный intellisense/typescript)! В большинстве случаев вы уже включили эту библиотеку, потому что от нее зависят (+-10 000) других библиотек.
Вы можете использовать fs.stat
, чтобы проверить, является ли цель файлом или каталогом, и вы можете использовать fs.access
, чтобы проверить, можете ли вы писать/читать/выполнять файл. (не забудьте использовать path.resolve
, чтобы получить полный путь к цели)
Документация:
Полный пример (TypeScript)
import * as fs from 'fs';
import * as path from 'path';
const targetPath = path.resolve(process.argv[2]);
function statExists(checkPath): Promise<fs.Stats> {
return new Promise((resolve) => {
fs.stat(checkPath, (err, result) => {
if (err) {
return resolve(undefined);
}
return resolve(result);
});
});
}
function checkAccess(checkPath: string, mode: number = fs.constants.F_OK): Promise<boolean> {
return new Promise((resolve) => {
fs.access(checkPath, mode, (err) => {
resolve(!err);
});
});
}
(async function () {
const result = await statExists(targetPath);
const accessResult = await checkAccess(targetPath, fs.constants.F_OK);
const readResult = await checkAccess(targetPath, fs.constants.R_OK);
const writeResult = await checkAccess(targetPath, fs.constants.W_OK);
const executeResult = await checkAccess(targetPath, fs.constants.X_OK);
const allAccessResult = await checkAccess(targetPath, fs.constants.F_OK | fs.constants.R_OK | fs.constants.W_OK | fs.constants.X_OK);
if (result) {
console.group('stat');
console.log('isFile: ', result.isFile());
console.log('isDir: ', result.isDirectory());
console.groupEnd();
}
else {
console.log('file/dir does not exist');
}
console.group('access');
console.log('access:', accessResult);
console.log('read access:', readResult);
console.log('write access:', writeResult);
console.log('execute access:', executeResult);
console.log('all (combined) access:', allAccessResult);
console.groupEnd();
process.exit(0);
}());
Для асинхронной версии! И с обещанной версией! Вот чистый простой способ!
try {
await fsPromise.stat(filePath);
/**
* File exists!
*/
// do something
} catch (err) {
if (err.code = 'ENOENT') {
/**
* File not found
*/
} else {
// Another error!
}
}
Более практичный фрагмент моего кода для лучшей иллюстрации:
try {
const filePath = path.join(FILES_DIR, fileName);
await fsPromise.stat(filePath);
/**
* File exists!
*/
const readStream = fs.createReadStream(
filePath,
{
autoClose: true,
start: 0
}
);
return {
success: true,
readStream
};
} catch (err) {
/**
* Mapped file doesn't exists
*/
if (err.code = 'ENOENT') {
return {
err: {
msg: 'Mapped file doesn\'t exists',
code: EErrorCode.MappedFileNotFound
}
};
} else {
return {
err: {
msg: 'Mapped file failed to load! File system error',
code: EErrorCode.MappedFileFileSystemError
}
};
}
}
Пример выше только для демонстрации! Я мог бы использовать событие ошибки потока чтения! Чтобы поймать любые ошибки! И пропустите два звонка!
Использование машинописного текста и fs/promises в node14
import * as fsp from 'fs/promises';
try{
const = await fsp.readFile(fullFileName)
...
} catch(e) { ...}
Лучше использовать fsp.readFile
, чем fsp.stat
или fsp.access
по двум причинам:
fsp.stat
и fsp.readFile
дадут разные ответы. Либо из-за тонких различий в вопросах, которые они задают, либо из-за того, что статус файлов изменился между звонками. Таким образом, кодировщику пришлось бы кодировать две условные ветви вместо одной, и пользователь мог бы увидеть больше вариантов поведения.
fs.access('file', err => err ? 'does not exist' : 'exists')
, см. fs.access. - person mb21   schedule 12.01.2019