【问题标题】:Node.js check if file existsNode.js 检查文件是否存在
【发布时间】:2013-07-15 23:52:43
【问题描述】:

如何检查文件是否存在?

在模块fs 的文档中,有对fs.exists(path, callback) 方法的描述。但是,据我了解,它只检查目录是否存在。我需要检查文件

如何做到这一点?

【问题讨论】:

  • 自 2018 年起,使用fs.access('file', err => err ? 'does not exist' : 'exists'),见fs.access

标签: node.js fs


【解决方案1】:

为什么不尝试打开文件呢? 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.existsfs.exists 均已弃用

使用 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
  • 任何正在阅读本文的人 (Node.js v0.12.x) 请记住,fs.existsfs.existsSync 也已被弃用。检查文件是否存在的最佳方法是fs.stat,如上所示。
  • 来自 Node js 文档,如果您打算在检查文件存在后打开文件,似乎最好的方法是实际打开它并在它不存在时处理错误。因为您的文件可能会在您的存在检查和打开功能之间被删除...
  • @Antrikshy fs.existsSync 不再被贬低,尽管fs.exists 仍然是。
【解决方案2】:

@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.'
  );


}

附:如果您还没有使用 fs-extra,请查看它——它非常棒。 https://github.com/jprichardson/node-fs-extra)

【讨论】:

    【解决方案3】:

    同步执行此操作的更简单方法。

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

    API 文档说明了existsSync 的工作原理:
    通过检查文件系统来测试给定路径是否存在。

    【讨论】:

    • @Imeurs but nodejs.org/api/fs.html#fs_fs_existssync_path 说:请注意 fs.exists() 已弃用,但 fs.existsSync() 不是。
    • fs.existsSync 已被弃用,但它不再是。
    • 同步“更容易”,但它也绝对更糟糕,因为你阻塞了等待 I/O 的整个进程,其他任务无法取得进展。拥抱承诺和异步,如果它不平凡,应用程序可能无论如何都必须使用它。
    【解决方案4】:

    在过去,我总是在坐下之前检查椅子是否在那里,然后我坐下,我有一个替代计划,比如坐在教练上。现在 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 );
        } );
    

    代码取自 2014 年 3 月的 http://fredkschott.com/post/2014/03/understanding-error-first-callbacks-in-node-js/,稍作修改以适应计算机。它还会检查权限 - 删除测试 chmod a-r foo.txt

    的权限

    【讨论】:

      【解决方案5】:

      fs.exists(path, callback)fs.existsSync(path) 现已弃用,请参阅 https://nodejs.org/api/fs.html#fs_fs_exists_path_callbackhttps://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.existsync 提供的链接清楚地表明它没有被弃用“注意 fs.exists() 已被弃用,但 fs.existsSync() 不是。(fs.existsync 的回调参数。 exists() 接受与其他 Node.js 回调不一致的参数。fs.existsSync() 不使用回调。)"
      • 第一个(从顶部开始)答案,其中提到了fs 变量的来源
      • 在撰写此答案时,信息是正确的;但是,fs.existsSync() 不再被弃用。
      • 很抱歉,“existsSync”确实已被弃用是什么意思?
      【解决方案6】:

      编辑: 由于节点v10.0.0我们可以使用fs.promises.access(...)

      检查文件是否存在的示例异步代码:

      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}´))
      

      扩展的 Promise 方式:

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

      【讨论】:

      • 赞成,这绝对是检测 Node.js 中是否存在文件的最现代(2018 年)方法
      • 是的,这是官方推荐的方法,用于简单地检查文件是否存在,之后不会进行操作。否则使用 open/write/read 并处理错误。 nodejs.org/api/fs.html#fs_fs_stat_path_callback
      • 在文档中我找到了fs.constants.F_OK 等。是否也可以像fs.F_OK 一样访问它们?诡异的。也很简洁,很好。
      • 可以尝试使用 fs.promises.access(path, fs.constants.F_OK); 来简单地使其成为 Promise 而不是创建 Promise。
      • 与简单的fs.exists 相比,这段代码实在是太难看了……真的很奇怪他们为什么强迫我们使用这样的替代方案:'-(
      【解决方案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
      【解决方案8】:

      嗯,我是这样做的,就像在 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');
        }
      });
      

      这有什么问题吗?

      【讨论】:

        【解决方案9】:
          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);
              }
            });
        

        【讨论】:

          【解决方案10】:

          V6 之前的旧版本: here's the documentation

            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 的新版本:documentation for fs.stat

          fs.stat('/etc/passwd', function(err, stat) {
              if(err == null) {
                  //Exist
              } else if(err.code == 'ENOENT') {
                  // NO exist
              } 
          });
          

          【讨论】:

          • 根据您分享的链接,fs.existsfs.existsSync 均已弃用。
          • existsSync 并未根据该文档被弃用,可能是您阅读它的时候。
          【解决方案11】:

          经过一番实验,我发现以下使用fs.stat 的示例是异步检查文件是否存在的好方法。它还会检查您的“文件”是否是“真正的文件”(而不是目录)。

          此方法使用 Promises,假设您使用的是异步代码库:

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

          如果文件不存在,promise 仍会解析,尽管false。如果文件确实存在,并且它是一个目录,则解析为true。任何试图读取文件的错误都会reject 承诺错误本身。

          【讨论】:

            【解决方案12】:

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

            docs 表示您应该使用access() 来替代已弃用的exists()

            带有内置 Promise 的 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 相比的优势在于,您可以使用这个包进行完整的输入(完整的智能感知/打字稿)!大多数情况下,您已经包含了这个库,因为 (+-10.000) 其他库依赖于它。

            【讨论】:

              【解决方案13】:

              有很多关于fs.existsSync() 被弃用的不准确的cmets;不是。

              https://nodejs.org/api/fs.html#fs_fs_existssync_path

              请注意 fs.exists() 已弃用,但 fs.existsSync() 不是。

              【讨论】:

                【解决方案14】:

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

                【讨论】:

                  【解决方案15】:

                  您可以使用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);
                  }());
                  

                  【讨论】:

                    【解决方案16】:

                    现代异步/等待方式(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 =&gt; fs.promises.stat(path).then(() =&gt; true, () =&gt; false);
                    【解决方案17】:

                    对于异步版本!并带有承诺版本!这是干净简单的方法!

                    try {
                        await fsPromise.stat(filePath);
                        /**
                         * File exists!
                         */
                        // do something
                    } catch (err) {
                        if (err.code = 'ENOENT') {
                            /**
                            * File not found
                            */
                        } else {
                            // Another error!
                        }
                    }
                    

                    我的代码中一个更实用的sn-p来更好地说明:

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

                    上面的例子只是为了演示!我本可以使用读取流的错误事件!捕捉任何错误!跳过这两个电话!

                    【讨论】:

                      【解决方案18】:

                      在 node14 中使用 typescript 和 fs/promises

                      import * as fsp from 'fs/promises';
                      try{
                      const = await fsp.readFile(fullFileName)
                      ...
                      } catch(e) { ...}
                      

                      使用fsp.readFile 比使用fsp.statfsp.access 更好,原因有二:

                      1. 最不重要的原因 - 少了一个访问权限。
                      2. fsp.statfsp.readFile 可能会给出不同的答案。要么是由于他们提出的问题存在细微差别,要么是因为文件状态在通话之间发生了变化。因此,编码人员必须编写两个条件分支而不是一个,用户可能会看到更多行为。

                      【讨论】:

                        【解决方案19】:

                        2021 年 8 月

                        看完所有帖子:

                        let filePath = "./directory1/file1.txt";
                        
                        if (fs.existsSync(filePath)) {
                            console.log("The file exists");
                        } else {
                            console.log("The file does not exist");
                        }
                        

                        【讨论】:

                          【解决方案20】:

                          async await 风格的简洁解决方案:

                          import { stat } from 'fs/promises';
                          
                          const exists = await stat('foo.txt')
                             .then(() => true)
                             .catch(() => false);
                          
                          

                          【讨论】:

                            猜你喜欢
                            • 2013-06-12
                            • 2013-11-09
                            • 2014-05-24
                            • 2018-06-10
                            • 1970-01-01
                            • 2015-02-16
                            • 2021-12-25
                            相关资源
                            最近更新 更多