Node.js проверяет, существует ли файл

147

Как я могу проверить наличие файла ?

В документации к модулю fsесть описание метода fs.exists(path, callback). Но, насколько я понимаю, проверяет наличие только каталогов. И мне нужно проверить файл !

Как это может быть сделано?

Роман Горбатко
источник
3
По состоянию на 2018 год используйте fs.access('file', err => err ? 'does not exist' : 'exists'), см. Fs.access
mb21,

Ответы:

231

Почему бы просто не попробовать открыть файл? 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);
    }
});
dardar.moh
источник
1
Но, как оказалось, fs.existsтоже работает. У меня возникли проблемы с правами доступа к файлу.
RomanGorbatko
11
path.existsна самом деле устарел в пользуfs.exists
Арно Ринкен
42
Любой, кто читает это сейчас (Node.js v0.12.x), должен помнить об этом, fs.existsи fs.existsSyncони также устарели. Лучший способ проверить существование файла fs.stat, как показано выше.
Antrikshy
8
Из документации Node js кажется, что лучший способ, если вы планируете открыть файл после проверки его существования, - это фактически открыть его и обработать ошибки, если они не существуют. Поскольку ваш файл может быть удален между вашей проверкой существования и функцией открытия ...
newprog
7
@Antrikshy fs.existsSyncбольше не издевается, хотя и fs.existsостается.
RyanZim
54

Более простой способ сделать это синхронно.

if (fs.existsSync('/etc/file')) {
    console.log('Found file');
}

Документ API говорит, как existsSyncработает:
проверьте, существует ли данный путь, проверив файловую систему.

Пол Хо
источник
13
fs.existsSync(path)устарело, см. nodejs.org/api/fs.html#fs_fs_existssync_path . fs.statSync(path)Рекомендуется синхронная реализация , см. Мой ответ.
lmeurs
20
@Imeurs, но nodejs.org/api/fs.html#fs_fs_existssync_path говорят: Обратите внимание, что fs.exists () устарела, а fs.existsSync () - нет.
HaveF
10
fs.existsSyncустарел, но больше не поддерживается.
RyanZim
52

Изменить: с узла 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;
}
мидо
источник
1
Проголосовали за, это определенно самый современный (2018) способ определить, существует ли файл в Node.js
AKMorris
1
Да, это официальный рекомендуемый метод, чтобы просто проверить, существует ли файл, и после этого не ожидается никаких манипуляций. В противном случае используйте open / write / read и обработайте ошибку. nodejs.org/api/fs.html#fs_fs_stat_path_callback
Джастин
1
В документации нахожу fs.constants.F_OKи т. Д. А можно ли к ним как fs.F_OK? Странно. Тоже лаконично, что приятно.
samson
1
Можно попробовать сделать это, fs.promises.access(path, fs.constants.F_OK);чтобы просто сделать это обещание вместо создания обещания.
Джереми Трпка,
Я использовал еще более короткую версию этого: не существует: !(await fs.stat(path).catch(() => false))существует:!!(await fs.stat(path).catch(() => false))
антитоксический
18

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.");
}
lmeurs
источник
10
Ссылка, которую вы предоставили для fs.existsync, четко указывает на то, что она НЕ устарела "Обратите внимание, что fs.exists () устарела, а fs.existsSync () - нет. (Параметр обратного вызова для fs.exists () принимает параметры, которые несовместимы с другими обратными вызовами Node.js. fs.existsSync () не использует обратный вызов.) "
shreddish
первый (сверху) ответ, в котором упоминалось, откуда fs
взялась
На момент написания этого ответа информация была верной; однако fs.existsSync()больше не рекомендуется к использованию.
RyanZim
15

Современный способ 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

Дмитрий Васильев
источник
13

Старая версия до 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
    } 
});
Игнасио Эрнандес
источник
1
Оба fs.existsи fs.existsSyncустарели в соответствии с предоставленной вами ссылкой.
Энди,
existsSyncне является устаревшим в соответствии с этим документом, может быть, когда вы его читали.
Darpan
7

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.
Wtower
6

@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 )

Mikermcneil
источник
3

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);
    }
  });
});
Александр Цайтлер
источник
2
  fs.statSync(path, function(err, stat){
      if(err == null) {
          console.log('File exists');
          //code when all ok
      }else if (err.code == "ENOENT") {
        //file doesn't exist
        console.log('not file');

      }
      else {
        console.log('Some other error: ', err.code);
      }
    });
Д.Бельда
источник
2

После небольшого экспериментирования я обнаружил, что следующий пример 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обещать ошибку.

f1lt3r
источник
1

Что ж, я сделал это так, как видно на 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');
  }
});

Есть ли с этим проблемы?

nthapa
источник
0

Раньше перед тем, как сесть, я всегда проверяю, есть ли стул, а затем сажусь в другом месте. У меня есть альтернативный план, например, сесть на тренера. Теперь сайт 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

user2167003
источник
0

обратный вызов vannilla Nodejs

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()

Nodejs со встроенным обещанием (узел 7+)

function fileExists(path, cb){
  return new Promise((accept,deny) => 
    fs.access(path, fs.constants.F_OK,(er, result)=> cb(!err && result))
  );
}

Популярный фреймворк javascript

fs-extra

var fs = require('fs-extra')
await fs.pathExists(filepath)

Как видите, намного проще. И преимущество перед promisify в том, что с этим пакетом у вас есть полная типизация (полный intellisense / typescript)! В большинстве случаев вы уже включили эту библиотеку, потому что (+ -10,000) от нее зависят другие библиотеки.

Джоэл Харкес
источник
0

Вы можете использовать, 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);
}());
BrunoLM
источник
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
            }
        }; 
   }
}

Приведенный выше пример предназначен только для демонстрации! Я мог бы использовать событие ошибки потока чтения! Чтобы ловить любые ошибки! И пропустите два звонка!

Мохамед Аллал
источник