Node.js controlla se il file esiste


143

Come posso verificare l'esistenza di un file ?

Nella documentazione per il modulo fsc'è una descrizione del metodo fs.exists(path, callback). Ma, a quanto ho capito, verifica l'esistenza di sole directory. E ho bisogno di controllare il file !

Come si può fare?


3
A partire dal 2018, usa fs.access('file', err => err ? 'does not exist' : 'exists'), vedi fs.access
mb21

Risposte:


227

Perché non provare ad aprire il file? fs.open('YourFile', 'a', function (err, fd) { ... }) comunque dopo un minuto di ricerca prova questo:

var path = require('path'); 

path.exists('foo.txt', function(exists) { 
  if (exists) { 
    // do something 
  } 
}); 

// or 

if (path.existsSync('foo.txt')) { 
  // do something 
} 

Per Node.js v0.12.x e versioni successive

Entrambi path.existse fs.existssono stati deprecati

*Modificare:

Cambiato: else if(err.code == 'ENOENT')

per: else if(err.code === 'ENOENT')

Linter si lamenta del fatto che il doppio uguale non sia il triplo uguale.

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

1
Ma, come si è scoperto, fs.existsfunziona anche. Ho avuto problemi con le autorizzazioni per il file.
RomanGorbatko,

11
path.existsin realtà è deprecato a favore difs.exists
Arnaud Rinquin

42
Chiunque legga questo ora (Node.js v0.12.x) deve tenerlo presente fs.existse fs.existsSyncanche essere stato deprecato. Il modo migliore per controllare l'esistenza dei file è fs.stat, come dimostrato sopra.
Antrikshy,

8
Dalla documentazione di Node js, sembra il modo migliore di procedere se si prevede di aprire il file dopo averne verificato l'esistenza, è aprirlo effettivamente e gestire gli errori se non esiste. Perché il tuo file potrebbe essere rimosso tra il tuo controllo esistente e la funzione open ...
newprog

6
@Antrikshy fs.existsSyncnon è più depresso, anche se fs.existslo è ancora.
RyanZim,

52

Un modo più semplice per farlo in modo sincrono.

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

Il documento API dice come existsSyncfunziona: verifica
se esiste il percorso indicato controllando con il file system.


12
fs.existsSync(path)è obsoleto ora, vedi nodejs.org/api/fs.html#fs_fs_existssync_path . Per un'implementazione sincrona fs.statSync(path)è consigliata, vedere la mia risposta.
Lmeurs,

20
@Imeurs ma nodejs.org/api/fs.html#fs_fs_existssync_path dice: Nota che fs.exists () è deprecato, ma fs.existsSync () non lo è.
HaveF

9
fs.existsSyncera deprecato, ma non lo è più.
RyanZim,

44

Modifica: dal nodo v10.0.0che potremmo usarefs.promises.access(...)

Esempio di codice asincrono che controlla l'esistenza del file:

async function checkFileExists(file) {
  return fs.promises.access(file, fs.constants.F_OK)
           .then(() => true)
           .catch(() => false)
}

Un'alternativa per stat potrebbe essere l'utilizzo del nuovo fs.access(...):

funzione di promessa breve minimizzata per il controllo:

s => new Promise(r=>fs.access(s, fs.constants.F_OK, e => r(!e)))

Esempio di utilizzo:

let checkFileExists = s => new Promise(r=>fs.access(s, fs.constants.F_OK, e => r(!e)))
checkFileExists("Some File Location")
  .then(bool => console.logfile exists: ${bool}´))

modo promesso ampliato:

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

o se vuoi farlo in modo sincrono:

function checkFileExistsSync(filepath){
  let flag = true;
  try{
    fs.accessSync(filepath, fs.constants.F_OK);
  }catch(e){
    flag = false;
  }
  return flag;
}

1
Sottoposto a votazione, questo è sicuramente il modo più moderno (2018) per rilevare se esiste un file in Node.js
AKMorris,

1
Sì, questo è il metodo ufficiale raccomandato per controllare semplicemente se il file esiste e non è prevista alcuna manipolazione in seguito. Altrimenti usa open / write / read e gestisci l'errore. nodejs.org/api/fs.html#fs_fs_stat_path_callback
Justin

1
Nella documentazione che trovo fs.constants.F_OKecc. È anche possibile accedervi come fs.F_OK? Strano. Anche conciso, il che è bello.
Sansone,

1
Potresti provare a farlo fs.promises.access(path, fs.constants.F_OK);semplicemente per renderlo una Promessa invece di creare una Promessa.
Jeremy Trpka,

18

fs.exists(path, callback)e fs.existsSync(path)ora sono deprecati, vedi https://nodejs.org/api/fs.html#fs_fs_exists_path_callback e https://nodejs.org/api/fs.html#fs_fs_existssync_path .

Per testare l'esistenza di un file in modo sincrono si può usare ie. fs.statSync(path). fs.StatsVerrà restituito un oggetto se il file esiste, vedere https://nodejs.org/api/fs.html#fs_class_fs_stats , altrimenti viene generato un errore che verrà rilevato dall'istruzione 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.");
}

10
Il link fornito per fs.existsync indica chiaramente che NON è deprecato "Nota che fs.exists () è deprecato, ma fs.existsSync () non lo è. (Il parametro callback per fs.exists () accetta parametri incoerenti con altri callback Node.js. fs.existsSync () non utilizza un callback.) "
shreddish

la prima (dall'alto) risposta, che menzionava da dove viene la fsvariabile
Dmitry Korolyov,

Al momento in cui questa risposta è stata scritta, l'informazione era corretta; tuttavia, fs.existsSync()non è più deprecato.
RyanZim,

12

Vecchia versione prima del V6: ecco la documentazione

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

AGGIORNARE

Nuove versioni da V6: documentazione perfs.stat

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

1
Entrambi fs.existse fs.existsSyncsono deprecati in base al link che hai condiviso.
Andy,

existsSyncnon è deprecato come da quel documento, potrebbe essere quando lo hai letto.
Darpan,

11

Modo asincrono / attesa moderno (Nodo 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();

Dobbiamo usare fs.stat() or fs.access()perché fs.exists(path, callback)ora è deprecato

Un altro buon modo è fs-extra


7

fs.existsè stato deprecato dalla 1.0.0. Puoi usare al fs.statposto di quello.

var fs = require('fs');
fs.stat(path, (err, stats) => {
if ( !stats.isFile(filename) ) { // do this 
}  
else { // do this 
}});

Ecco il link per la documentazione fs.stats


stats.isFile()non ha bisogno filename.
Wtower,

6

@Fox: ottima risposta! Ecco un po 'di estensione con alcune opzioni in più. È quello che ho usato di recente come soluzione di riferimento:

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 dai un'occhiata a fs-extra se non lo stai già usando, è piuttosto dolce. https://github.com/jprichardson/node-fs-extra )



3

async/awaitversione usando util.promisifydal Nodo 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

Dopo un po 'di sperimentazione, ho trovato il seguente esempio usando fs.statcome un buon modo per verificare in modo asincrono se esiste un file. Verifica inoltre che il "file" sia "veramente-è-un-file" (e non una directory).

Questo metodo utilizza Promises, supponendo che tu stia lavorando con una base di codice asincrona:

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

Se il file non esiste, la promessa si risolve comunque, anche se false. Se il file esiste ed è una directory, viene risolto true. Eventuali errori nel tentativo di leggere il file rejectpromettono l'errore stesso.


1

Bene, l'ho fatto in questo modo, come visto su 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');
  }
});

C'è qualche problema con questo?


0

ai vecchi tempi prima di sedermi controllo sempre se c'è la sedia, poi mi siedo altrimenti ho un piano alternativo come sedermi su un pullman. Ora il sito node.js suggerisce di andare (non è necessario controllare) e la risposta è simile alla seguente:

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

codice tratto da http://fredkschott.com/post/2014/03/understanding-error-first-callbacks-in-node-js/ da marzo 2014 e leggermente modificato per adattarsi al computer. Controlla anche l'autorizzazione - rimuove l'autorizzazione per il testchmod a-r foo.txt


0

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

i documenti dicono che dovresti usare access()come sostituto per deprecatoexists()

Nodejs con build in promise (nodo 7+)

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

Framework javascript popolare

FS-extra

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

Come vedi molto più semplice. E il vantaggio rispetto a promisify è che hai a disposizione digitazioni complete con questo pacchetto (intellisense / dattiloscritto completo)! La maggior parte dei casi avrai già incluso questa libreria perché (+ -10.000) altre librerie dipendono da essa.


0

È possibile utilizzare fs.statper verificare se target è un file o una directory e è possibile utilizzare fs.accessper verificare se è possibile scrivere / leggere / eseguire il file. (ricorda di usare path.resolveper ottenere il percorso completo per il bersaglio)

Documentazione:

Esempio completo (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);
}());

0

Per la versione asincrona! E con la versione promessa! Ecco il modo semplice e pulito!

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

Uno snippet più pratico dal mio codice per illustrare meglio:


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

L'esempio sopra è solo per dimostrazione! Avrei potuto usare l'evento di errore del flusso di lettura! Per rilevare eventuali errori! E salta le due chiamate!

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.