Как я могу проверить наличие файла ?
В документации к модулю 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')
кому: 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
тоже работает. У меня возникли проблемы с правами доступа к файлу.
path.exists
на самом деле устарел в пользуfs.exists
fs.exists
и fs.existsSync
они также устарели. Лучший способ проверить существование файла fs.stat
, как показано выше.
fs.existsSync
больше не издевается, хотя и fs.exists
остается.
Более простой способ сделать это синхронно.
if (fs.existsSync('/etc/file')) {
console.log('Found file');
}
Документ API говорит, как existsSync
работает:
проверьте, существует ли данный путь, проверив файловую систему.
fs.existsSync(path)
устарело, см. nodejs.org/api/fs.html#fs_fs_existssync_path . fs.statSync(path)
Рекомендуется синхронная реализация , см. Мой ответ.
fs.existsSync
устарел, но больше не поддерживается.
Изменить:
с узла v10.0.0
мы могли бы использоватьfs.promises.access(...)
Пример асинхронного кода, который проверяет, существует ли файл:
async function checkFileExists(file) {
return fs.promises.access(file, fs.constants.F_OK)
.then(() => true)
.catch(() => false)
}
Альтернативой stat может быть новый 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
? Странно. Тоже лаконично, что приятно.
fs.promises.access(path, fs.constants.F_OK);
чтобы просто сделать это обещание вместо создания обещания.
!(await fs.stat(path).catch(() => false))
существует:!!(await fs.stat(path).catch(() => false))
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 , в противном случае выдается ошибка , которая будет пойманное заявлением попытки / поймать.
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
fs.existsSync()
больше не рекомендуется к использованию.
Современный способ 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
Старая версия до 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
устарели в соответствии с предоставленной вами ссылкой.
existsSync
не является устаревшим в соответствии с этим документом, может быть, когда вы его читали.
@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.'
);
}
PS проверьте fs-extra, если вы еще не используете его - это довольно мило. https://github.com/jprichardson/node-fs-extra )
Есть много неточных комментариев по поводу 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.access('file', err => err ? 'does not exist' : 'exists')
, см. Fs.access