Node.js sprawdza, czy plik istnieje

143

Jak sprawdzić istnienie pliku ?

W dokumentacji modułu fsznajduje się opis metody fs.exists(path, callback). Ale, jak rozumiem, sprawdza, czy istnieją tylko katalogi. I muszę sprawdzić plik !

Jak to zrobić?

RomanGorbatko
źródło
3
Począwszy od 2018 roku, fs.access('file', err => err ? 'does not exist' : 'exists')patrz fs.access
mb21

Odpowiedzi:

227

Dlaczego po prostu nie spróbować otworzyć pliku? fs.open('YourFile', 'a', function (err, fd) { ... }) w każdym razie po minucie wyszukiwania spróbuj tego:

var path = require('path'); 

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

// or 

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

Dla Node.js v0.12.xi nowszych

Obie path.existsi fs.existszostały wycofane

*Edytować:

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

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

Linter narzeka, że ​​podwójne równa się, a nie potrójne równe.

Korzystanie z 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
źródło
1
Ale, jak się okazało, fs.existsteż działa. Miałem problemy z uprawnieniami do pliku.
RomanGorbatko,
11
path.existsfaktycznie jest przestarzały na korzyśćfs.exists
Arnaud Rinquin
42
Każdy, kto czyta to teraz (Node.js v0.12.x), pamiętaj o tym fs.existsi fs.existsSyncrównież został uznany za przestarzały. Najlepszym sposobem sprawdzenia istnienia pliku jest fs.statpokazany powyżej.
Antrikshy
8
Z dokumentacji Node js wydaje się, że najlepszym sposobem, jeśli planujesz otworzyć plik po sprawdzeniu jego istnienia, jest faktyczne otwarcie go i naprawienie błędów, jeśli nie istnieje. Ponieważ twój plik może zostać usunięty między sprawdzeniem istnienia a funkcją open ...
newprog
6
@Antrikshy fs.existsSyncnie jest już pozbawiony praw, chociaż fs.existsnadal jest.
RyanZim
52

Łatwiejszy sposób na zrobienie tego synchronicznie.

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

Dokument API mówi, jak existsSyncdziała:
sprawdź, czy podana ścieżka istnieje, sprawdzając w systemie plików.

Paul Ho
źródło
12
fs.existsSync(path)jest teraz przestarzała, zobacz nodejs.org/api/fs.html#fs_fs_existssync_path . W przypadku synchronicznej implementacji fs.statSync(path), zobacz moją odpowiedź.
lmeurs
20
@Imeurs, ale nodejs.org/api/fs.html#fs_fs_existssync_path mówi: Zauważ, że fs.exists () jest przestarzałe, ale fs.existsSync () nie.
HaveF
9
fs.existsSynczostał wycofany, ale już nim nie jest.
RyanZim
44

Edycja: Od węzła v10.0.0możemy użyćfs.promises.access(...)

Przykładowy kod asynchroniczny, który sprawdza, czy plik istnieje:

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

Alternatywą dla statystyki może być użycie nowego fs.access(...):

zminimalizowana funkcja krótkiej obietnicy do sprawdzania:

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

Przykładowe użycie:

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

rozszerzony sposób 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);
    });
  });
}

lub jeśli chcesz to zrobić synchronicznie:

function checkFileExistsSync(filepath){
  let flag = true;
  try{
    fs.accessSync(filepath, fs.constants.F_OK);
  }catch(e){
    flag = false;
  }
  return flag;
}
mido
źródło
1
Za uznaniem, jest to zdecydowanie najnowocześniejszy (2018) sposób na wykrycie, czy plik istnieje w Node.js
AKMorris
1
Tak, jest to oficjalna zalecana metoda prostego sprawdzenia, czy plik istnieje i nie oczekuje się późniejszej manipulacji. W przeciwnym razie użyj opcji open / write / read i obsłuż błąd. nodejs.org/api/fs.html#fs_fs_stat_path_callback
Justin
1
W dokumentacji, którą znajduję fs.constants.F_OKitp. Czy można również uzyskać do nich dostęp fs.F_OK? Dziwne. Również zwięzłe, co jest miłe.
samson
1
Można spróbować zrobić to fs.promises.access(path, fs.constants.F_OK);po prostu jako Obietnica zamiast tworzyć Obietnicę.
Jeremy Trpka
18

fs.exists(path, callback)i fs.existsSync(path)są teraz przestarzałe, zobacz https://nodejs.org/api/fs.html#fs_fs_exists_path_callback i https://nodejs.org/api/fs.html#fs_fs_existssync_path .

Aby przetestować istnienie pliku synchronicznie, można użyć np. fs.statSync(path). fs.StatsZostanie zwrócony obiekt, jeśli plik istnieje, patrz https://nodejs.org/api/fs.html#fs_class_fs_stats , w przeciwnym razie zostanie zgłoszony błąd, który zostanie przechwycony przez instrukcję 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.");
}
lmeurs
źródło
10
Odnośnik, który podałeś dla fs.existsync jasno pokazuje, że NIE jest przestarzały. ”Zauważ, że fs.exists () jest przestarzałe, ale fs.existsSync () nie jest. (Parametr wywołania zwrotnego funkcji fs.exists () akceptuje parametry, które są niespójne z innymi wywołaniami zwrotnymi Node.js. fs.existsSync () nie używa wywołania zwrotnego.) "
shreddish
pierwsza (od góry) odpowiedź, w której wspomniano, skąd fspochodzi zmienna
Dmitry Korolyov
W momencie pisania tej odpowiedzi informacje były poprawne; jednak fs.existsSync()nie jest już przestarzały.
RyanZim
12

Stara wersja przed V6: oto dokumentacja

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

AKTUALIZACJA

Nowe wersje z V6: dokumentacja dlafs.stat

fs.stat('/etc/passwd', function(err, stat) {
    if(err == null) {
        //Exist
    } else if(err.code == 'ENOENT') {
        // NO exist
    } 
});
Ignacio Hernández
źródło
1
Obie fs.existsi fs.existsSyncsą przestarzałe zgodnie z udostępnionym przez Ciebie linkiem.
Andy
existsSyncnie jest przestarzały zgodnie z tym dokumentem, może to być, gdy go czytałeś.
Darpan
11

Nowoczesny sposób 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();

Musimy użyć, fs.stat() or fs.access()ponieważ fs.exists(path, callback)teraz jest przestarzały

Innym dobrym sposobem jest fs-extra

Дмитрий Васильев
źródło
7

fs.existsjest przestarzały od 1.0.0. Możesz użyć fs.statzamiast tego.

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

Oto link do dokumentacji fs.stats

Koushik Das
źródło
stats.isFile()nie potrzebuje filename.
Wtower
6

@Fox: świetna odpowiedź! Oto trochę rozszerzenia z kilkoma dodatkowymi opcjami. To jest to, czego ostatnio używam jako rozwiązanie:

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 sprawdź fs-extra, jeśli jeszcze go nie używasz - to całkiem słodkie. https://github.com/jprichardson/node-fs-extra )

mikermcneil
źródło
3

async/awaitwersja używająca util.promisifyod Węzła 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);
    }
  });
});
Alexander Zeitler
źródło
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);
      }
    });
D.Belda
źródło
2

Po krótkich eksperymentach stwierdziłem, że poniższy przykład fs.statjest dobrym sposobem asynchronicznego sprawdzania, czy plik istnieje. Sprawdza również, czy Twój „plik” to „naprawdę-jest-plikiem” (a nie katalogiem).

Ta metoda używa Promises, zakładając, że pracujesz z asynchroniczną bazą kodu:

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

Jeśli plik nie istnieje, obietnica nadal zostanie rozwiązana false. Jeśli plik istnieje i jest katalogiem, zostanie rozwiązany true. Wszelkie błędy przy próbie odczytania pliku będą rejectobietnicą samego błędu.

f1lt3r
źródło
1

Cóż, zrobiłem to w ten sposób, jak widać na 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');
  }
});

Czy jest z tym jakiś problem?

nthapa
źródło
0

w dawnych czasach przed siadaniem zawsze sprawdzam, czy jest krzesło, potem siadam, mam inny plan, jak siedzenie na trenerze. Teraz witryna node.js sugeruje przejście (nie trzeba sprawdzać), a odpowiedź wygląda następująco:

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

kod zaczerpnięty z http://fredkschott.com/post/2014/03/understanding-error-first-callbacks-in-node-js/ z marca 2014 roku i nieco zmodyfikowany, aby pasował do komputera. Sprawdza również uprawnienia - usuń uprawnienia do testowaniachmod a-r foo.txt

user2167003
źródło
0

vannilla Nodejs callback

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

z docs powiedzieć należy użyć access()jako zamiennik za przestarzałeexists()

Nodejs z obietnicą kompilacji (węzeł 7+)

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

Popularny framework javascript

FS-extra

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

Jak widać o wiele prostsze. A zaletą w stosunku do obietnicy jest to, że w tym pakiecie masz kompletną pisownię (pełna inteligencja / maszynopis)! W większości przypadków uwzględnisz już tę bibliotekę, ponieważ (+ -10.000) inne biblioteki są od niej zależne.

Joel Harkes
źródło
0

Możesz użyć fs.statdo sprawdzenia, czy cel jest plikiem lub katalogiem i możesz użyć fs.accessdo sprawdzenia, czy możesz zapisać / odczytać / wykonać plik. (pamiętaj, aby użyć, path.resolveaby uzyskać pełną ścieżkę do celu)

Dokumentacja:

Pełny przykład (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
źródło
0

Dla wersji asynchronicznej! I w wersji obiecanej! Tutaj czysty, prosty sposób!

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

Bardziej praktyczny fragment mojego kodu, aby lepiej zilustrować:


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

Powyższy przykład służy tylko do demonstracji! Mogłem użyć zdarzenia błędu strumienia odczytu! Wyłapać błędy! I pomiń te dwie rozmowy!

Mohamed Allal
źródło