Wie kann ich mithilfe von node.js synchron prüfen, ob eine Datei oder ein Verzeichnis vorhanden ist?
exists
fügt async in diesem Fall nur unnötige Rückrufe hinzu.
Wie kann ich mithilfe von node.js synchron prüfen, ob eine Datei oder ein Verzeichnis vorhanden ist?
exists
fügt async in diesem Fall nur unnötige Rückrufe hinzu.
Antworten:
Die Antwort auf diese Frage hat sich im Laufe der Jahre geändert. Die aktuelle Antwort befindet sich hier oben, gefolgt von den verschiedenen Antworten im Laufe der Jahre in chronologischer Reihenfolge:
Sie können verwenden fs.existsSync()
:
const fs = require("fs"); // Or `import fs from "fs";` with ESM
if (fs.existsSync(path)) {
// Do something
}
Es war mehrere Jahre veraltet, ist es aber nicht mehr. Aus den Dokumenten:
Beachten Sie, dass dies
fs.exists()
veraltet ist, aberfs.existsSync()
nicht. (Der Rückrufparameter zumfs.exists()
Akzeptieren von Parametern, die nicht mit anderen Node.js-Rückrufen übereinstimmen.fs.existsSync()
Verwendet keinen Rückruf.)
Sie haben ausdrücklich um eine synchrone Prüfung gebeten. Wenn Sie jedoch stattdessen eine asynchrone Prüfung verwenden können (normalerweise am besten mit E / A), verwenden fs.promises.access
Sie diese , wenn Sie async
Funktionen verwenden, oder fs.access
(da sie exists
veraltet ist ), wenn nicht:
In einer async
Funktion:
try {
await fs.promises.access("somefile");
// The check succeeded
} catch (error) {
// The check failed
}
Oder mit einem Rückruf:
fs.access("somefile", error => {
if (!error) {
// The check succeeded
} else {
// The check failed
}
});
Hier sind die historischen Antworten in chronologischer Reihenfolge:
stat
/ statSync
oder lstat
/ lstatSync
)exists
/ existsSync
)exists
/ existsSync
sind wir wahrscheinlich wieder bei stat
/ statSync
oder lstat
/ lstatSync
)fs.access(path, fs.F_OK, function(){})
/ fs.accessSync(path, fs.F_OK)
, aber das zur Kenntnis , wenn die Datei / Verzeichnis nicht vorhanden ist , dann ist es ein Fehler, docs für fs.stat
empfehlen die Verwendung , fs.access
wenn Sie benötigen die Existenz ohne Öffnung zu überprüfen)fs.exists()
ist immer noch veraltet, aber fs.existsSync()
nicht mehr veraltet. So können Sie es jetzt sicher verwenden.Sie können statSync
oder lstatSync
( docs link ) verwenden, um ein fs.Stats
Objekt zu erhalten . Wenn eine synchrone Version einer Funktion verfügbar ist, hat sie im Allgemeinen denselben Namen wie die asynchrone Version Sync
am Ende. So statSync
ist die synchrone Version von stat
; lstatSync
ist die synchrone Version von lstat
usw.
lstatSync
Hier erfahren Sie sowohl, ob etwas vorhanden ist, als auch, ob es sich um eine Datei oder ein Verzeichnis handelt (oder in einigen Dateisystemen um eine symbolische Verknüpfung, ein Blockgerät, ein Zeichengerät usw.), z. B. ob Sie wissen müssen, ob es vorhanden ist und vorhanden ist ein Verzeichnis:
var fs = require('fs');
try {
// Query the entry
stats = fs.lstatSync('/the/path');
// Is it a directory?
if (stats.isDirectory()) {
// Yes it is
}
}
catch (e) {
// ...
}
... und ähnlich, wenn es eine Datei ist, gibt es isFile
; Wenn es sich um ein Blockgerät handelt, gibt es isBlockDevice
usw. usw. Beachten Sie die try/catch
; Es wird ein Fehler ausgegeben, wenn der Eintrag überhaupt nicht vorhanden ist.
Wenn es Ihnen egal ist, was der Eintrag ist, und Sie nur wissen möchten, ob er vorhanden ist, können Sie path.existsSync
(oder mit der neuesten Versionfs.existsSync
) Folgendes verwenden , wie von user618408 angegeben :
var path = require('path');
if (path.existsSync("/the/path")) { // or fs.existsSync
// ...
}
Es erfordert kein try/catch
, gibt Ihnen aber keine Informationen darüber, was das Ding ist, nur dass es da ist. path.existsSync
wurde vor langer Zeit veraltet.
Randnotiz: Sie haben ausdrücklich gefragt, wie Sie synchron prüfen sollen , daher habe ich die xyzSync
Versionen der oben genannten Funktionen verwendet. Bei E / A ist es jedoch am besten, synchrone Anrufe zu vermeiden. Anrufe in das E / A-Subsystem nehmen aus Sicht einer CPU viel Zeit in Anspruch. Beachten Sie, wie einfach es ist, anzurufen, lstat
anstatt lstatSync
:
// Is it a directory?
lstat('/the/path', function(err, stats) {
if (!err && stats.isDirectory()) {
// Yes it is
}
});
Aber wenn Sie die synchrone Version benötigen, ist sie da.
Die folgende Antwort von vor ein paar Jahren ist jetzt etwas veraltet. Die derzeitige Methode besteht darin fs.existsSync
, eine synchrone Prüfung auf Datei- / Verzeichnisexistenz (oder natürlich fs.exists
eine asynchrone Prüfung) anstelle der folgenden path
Versionen durchzuführen.
Beispiel:
var fs = require('fs');
if (fs.existsSync(path)) {
// Do something
}
// Or
fs.exists(path, function(exists) {
if (exists) {
// Do something
}
});
Und hier sind wir im Jahr 2015 und die Node-Dokumente sagen jetzt, dass fs.existsSync
(und fs.exists
) "veraltet sein werden". (Weil die Node-Leute denken, es sei dumm zu prüfen, ob etwas existiert, bevor sie es öffnen, was es ist; aber das ist nicht der einzige Grund, um zu überprüfen, ob etwas existiert!)
Wir sind also wahrscheinlich wieder bei den verschiedenen stat
Methoden ... Bis sich dies natürlich noch einmal ändert.
Ich weiß nicht, wie lange es schon da ist, aber es gibt auch fs.access(path, fs.F_OK, ...)
/fs.accessSync(path, fs.F_OK)
. Zumindest ab Oktober 2016 wird in der fs.stat
Dokumentation empfohlen fs.access
, Existenzprüfungen durchzuführen ( "Es fs.access()
wird empfohlen, zu überprüfen, ob eine Datei vorhanden ist, ohne sie anschließend zu bearbeiten." ). Beachten Sie jedoch, dass der nicht verfügbare Zugriff als Fehler angesehen wird. Dies ist wahrscheinlich am besten, wenn Sie erwarten, dass auf die Datei zugegriffen werden kann:
var fs = require('fs');
try {
fs.accessSync(path, fs.F_OK);
// Do something
} catch (e) {
// It isn't accessible
}
// Or
fs.access(path, fs.F_OK, function(err) {
if (!err) {
// Do something
} else {
// It isn't accessible
}
});
Sie können verwenden fs.existsSync()
:
if (fs.existsSync(path)) {
// Do something
}
Es war mehrere Jahre veraltet, ist es aber nicht mehr. Aus den Dokumenten:
Beachten Sie, dass dies
fs.exists()
veraltet ist, aberfs.existsSync()
nicht. (Der Rückrufparameter zumfs.exists()
Akzeptieren von Parametern, die nicht mit anderen Node.js-Rückrufen übereinstimmen.fs.existsSync()
Verwendet keinen Rückruf.)
open
Aufruf auszugeben und die Ausnahme zu behandeln, oder was auch immer, wenn die Datei nicht war gefunden. Schließlich ist die reale Welt chaotisch: Wenn Sie zuerst nachsehen, ob sie da ist, heißt das nicht, dass sie immer noch da ist, wenn Sie versuchen, sie zu öffnen. Wenn Sie zuerst nachsehen und es nicht da ist, heißt das nicht, dass es einen Moment später nicht da sein wird. Timing Dinge wie das scheint wie Grenzfälle, aber sie kommen die ganze Zeit . Also , wenn Sie öffnen gehen, kein Punkt bei der Prüfung zuerst.
Wenn man sich die Quelle ansieht, gibt es eine synchrone Version von path.exists
- path.existsSync
. Sieht so aus, als wäre es in den Dokumenten übersehen worden.
path.exists
und path.existsSync
sind jetzt veraltet . Bitte benutzen Sie .fs.exists
undfs.existsSync
fs.exists
und veraltet . Verwenden Sie stattdessen fs.stat () oder fs.access () .fs.existsSync
wurden ebenfalls
verwenden fs.existsSync
. Es ist nicht veraltet.
https://nodejs.org/api/fs.html#fs_fs_existssync_path
fs.existsSync
.
exists
Funktion zu ersetzen :is-there
fs.exists
als veraltet gekennzeichnet, solange dies fs.existsSync
nicht der Fall ist!
Mit den derzeit empfohlenen (ab 2015) APIs (gemäß den Knotendokumenten) mache ich Folgendes:
var fs = require('fs');
function fileExists(filePath)
{
try
{
return fs.statSync(filePath).isFile();
}
catch (err)
{
return false;
}
}
Als Antwort auf das von @broadband in den Kommentaren angesprochene EPERM-Problem bringt dies einen guten Punkt hervor. fileExists () ist in vielen Fällen wahrscheinlich keine gute Möglichkeit, darüber nachzudenken, da fileExists () eine boolesche Rückgabe nicht wirklich versprechen kann. Möglicherweise können Sie definitiv feststellen, ob die Datei vorhanden ist oder nicht, aber möglicherweise wird auch ein Berechtigungsfehler angezeigt. Der Berechtigungsfehler bedeutet nicht unbedingt, dass die Datei vorhanden ist, da Ihnen möglicherweise die Berechtigung für das Verzeichnis fehlt, das die Datei enthält, die Sie überprüfen. Und natürlich besteht die Möglichkeit, dass bei der Überprüfung der Dateidexistenz ein anderer Fehler auftritt.
Mein Code oben lautet also wirklich doesFileExistAndDoIHaveAccessToIt (), aber Ihre Frage könnte doesFileNotExistAndCouldICreateIt () sein, was eine völlig andere Logik wäre (die unter anderem einen EPERM-Fehler berücksichtigen müsste).
Während die Antwort von fs.existsSync die hier gestellte Frage direkt anspricht, wird dies oft nicht das sein, was Sie wollen (Sie möchten nicht nur wissen, ob "etwas" auf einem Pfad vorhanden ist, Sie interessieren sich wahrscheinlich dafür, ob das "Ding" das existiert ist eine Datei oder ein Verzeichnis).
Wenn Sie überprüfen, ob eine Datei vorhanden ist, tun Sie dies wahrscheinlich, weil Sie beabsichtigen, basierend auf dem Ergebnis eine Aktion auszuführen, und diese Logik (die Überprüfung und / oder die nachfolgende Aktion) sollte die Idee berücksichtigen dass ein Objekt, das sich in diesem Pfad befindet, eine Datei oder ein Verzeichnis sein kann und dass bei der Überprüfung möglicherweise EPERM oder andere Fehler auftreten.
file.exists()
Nutzen für die 3% haben und uns stattdessen zwingen, dies in einen Try-Catch zu packen? Werden Sie echt ... Schlampe des Tages.
Ein weiteres Update
Ich brauchte selbst eine Antwort auf diese Frage. Ich habe die Knotendokumente nachgeschlagen. Anscheinend sollten Sie nicht fs.exists verwenden, sondern fs.open verwenden und den ausgegebenen Fehler verwenden, um festzustellen, ob eine Datei nicht vorhanden ist:
aus den Dokumenten:
fs.exists () ist ein Anachronismus und existiert nur aus historischen Gründen. Es sollte fast nie einen Grund geben, es in Ihrem eigenen Code zu verwenden.
Insbesondere die Überprüfung, ob eine Datei vor dem Öffnen vorhanden ist, ist ein Anti-Pattern, das Sie für Race-Bedingungen anfällig macht: Ein anderer Prozess kann die Datei zwischen den Aufrufen von fs.exists () und fs.open () entfernen. Öffnen Sie einfach die Datei und behandeln Sie den Fehler, wenn er nicht vorhanden ist.
Ich benutze die folgende Funktion, um zu testen, ob eine Datei existiert. Es werden auch andere Ausnahmen erfasst. Falls es also Rechteprobleme gibt, z. B. chmod ugo-rwx filename
oder in der Windows-
Right Click -> Properties -> Security -> Advanced -> Permission entries: empty list ..
Funktion, wird die Ausnahme wie gewünscht zurückgegeben. Die Datei ist vorhanden, wir haben jedoch keine Zugriffsrechte. Es wäre falsch, solche Ausnahmen zu ignorieren.
function fileExists(path) {
try {
return fs.statSync(path).isFile();
}
catch (e) {
if (e.code == 'ENOENT') { // no such file or directory. File really does not exist
console.log("File does not exist.");
return false;
}
console.log("Exception fs.statSync (" + path + "): " + e);
throw e; // something else went wrong, we don't have rights, ...
}
}
Ausnahmeausgabe, NodeJS-Fehlerdokumentation für den Fall, dass keine Datei vorhanden ist:
{
[Error: ENOENT: no such file or directory, stat 'X:\\delsdfsdf.txt']
errno: -4058,
code: 'ENOENT',
syscall: 'stat',
path: 'X:\\delsdfsdf.txt'
}
Ausnahme für den Fall, dass wir keine Rechte an der Datei haben, aber vorhanden sind:
{
[Error: EPERM: operation not permitted, stat 'X:\file.txt']
errno: -4048,
code: 'EPERM',
syscall: 'stat',
path: 'X:\\file.txt'
}
fs.exists () ist veraltet. Verwenden Sie es nicht https://nodejs.org/api/fs.html#fs_fs_exists_path_callback
Sie können die hier verwendete Methode für den Kernknoten implementieren: https://github.com/nodejs/node-v0.x-archive/blob/master/lib/module.js#L86
function statPath(path) {
try {
return fs.statSync(path);
} catch (ex) {}
return false;
}
Dadurch wird das Statistikobjekt zurückgegeben. Sobald Sie das Statistikobjekt haben, können Sie es versuchen
var exist = statPath('/path/to/your/file.js');
if(exist && exist.isFile()) {
// do something
}
Einige Antworten hier sagen das fs.exists
und fs.existsSync
sind beide veraltet. Laut den Dokumenten ist dies nicht mehr wahr. Nur fs.exists
ist jetzt veraltet:
Beachten Sie, dass fs.exists () veraltet ist, fs.existsSync () jedoch nicht. (Der Rückrufparameter für fs.exists () akzeptiert Parameter, die nicht mit anderen Node.js-Rückrufen übereinstimmen. Fs.existsSync () verwendet keinen Rückruf.)
Sie können also sicher mit fs.existsSync () synchron prüfen, ob eine Datei vorhanden ist.
Das path
Modul bietet keine synchrone Version von, path.exists
sodass Sie mit dem fs
Modul herumspielen müssen.
Das Schnellste, was ich mir vorstellen kann, ist die Verwendung fs.realpathSync
eines Fehlers, den Sie abfangen müssen. Sie müssen also Ihre eigene Wrapper-Funktion mit einem Versuch / Fang erstellen.
Die Verwendung von fileSystem (fs) -Tests löst Fehlerobjekte aus, die Sie dann in eine try / catch-Anweisung einschließen müssten. Sparen Sie sich Mühe und verwenden Sie eine Funktion, die im Zweig 0.4.x eingeführt wurde.
var path = require('path');
var dirs = ['one', 'two', 'three'];
dirs.map(function(dir) {
path.exists(dir, function(exists) {
var message = (exists) ? dir + ': is a directory' : dir + ': is not a directory';
console.log(message);
});
});
Die Dokumente auf fs.stat()
sagt zu verwendenfs.access()
wenn die Datei nicht bearbeitet werden soll. Es gab keine Rechtfertigung, könnte schneller oder weniger Speicher verwendet werden?
Ich verwende Node für die lineare Automatisierung, daher dachte ich, ich teile die Funktion, mit der ich die Existenz von Dateien teste.
var fs = require("fs");
function exists(path){
//Remember file access time will slow your program.
try{
fs.accessSync(path);
} catch (err){
return false;
}
return true;
}
aktualisiert asnwer für jene Leute 'richtig', die darauf hinweisen, dass es die Frage nicht direkt beantwortet, mehr bringen eine alternative Option.
fs.existsSync('filePath')
auch hier sehen docs .
Gibt true zurück, wenn der Pfad vorhanden ist, andernfalls false.
In einem asynchronen Kontext können Sie die asynchrone Version einfach synchron mit dem await
Schlüsselwort schreiben . Sie können die asynchrone Rückrufmethode einfach in ein Versprechen wie das folgende umwandeln:
function fileExists(path){
return new Promise((resolve, fail) => fs.access(path, fs.constants.F_OK,
(err, result) => err ? fail(err) : resolve(result))
//F_OK checks if file is visible, is default does no need to be specified.
}
async function doSomething() {
var exists = await fileExists('filePath');
if(exists){
console.log('file exists');
}
}
die Dokumente bei access ().
function asyncFileExists(path) { //F_OK checks if file is visible, is default does no need to be specified. return new Promise(function (res, rej) { fs.access( path, fs.constants.F_OK, function (err) { err ? rej(err) : res(true); }, ); }); }
Wenn Sie wissen möchten, ob eine Datei vorhanden ist, möchten Sie diese möglicherweise anfordern, wenn dies der Fall ist.
function getFile(path){
try{
return require(path);
}catch(e){
return false;
}
}
Hier ist eine einfache Wrapper-Lösung dafür:
var fs = require('fs')
function getFileRealPath(s){
try {return fs.realpathSync(s);} catch(e){return false;}
}
Verwendungszweck:
Beispiel:
var realPath,pathToCheck='<your_dir_or_file>'
if( (realPath=getFileRealPath(pathToCheck)) === false){
console.log('file/dir not found: '+pathToCheck);
} else {
console.log('file/dir exists: '+realPath);
}
Stellen Sie sicher, dass Sie den Operator === verwenden, um zu testen, ob return gleich false ist. Es gibt keinen logischen Grund, warum fs.realpathSync () unter geeigneten Arbeitsbedingungen false zurückgeben würde, daher denke ich, dass dies zu 100% funktionieren sollte.
Ich würde es vorziehen, eine Lösung zu sehen, die keinen Fehler und keinen daraus resultierenden Leistungseinbruch erzeugt. Aus API-Sicht scheint fs.exists () die eleganteste Lösung zu sein.
Aus den Antworten geht hervor, dass es hierfür keine offizielle API-Unterstützung gibt (wie bei einer direkten und expliziten Überprüfung). Viele der Antworten sagen, dass stat verwendet werden soll, sie sind jedoch nicht streng. Wir können zum Beispiel nicht davon ausgehen, dass ein von stat ausgelöster Fehler bedeutet, dass etwas nicht existiert.
Nehmen wir an, wir versuchen es mit etwas, das es nicht gibt:
$ node -e 'require("fs").stat("god",err=>console.log(err))'
{ Error: ENOENT: no such file or directory, stat 'god' errno: -2, code: 'ENOENT', syscall: 'stat', path: 'god' }
Versuchen wir es mit etwas, das existiert, auf das wir aber keinen Zugriff haben:
$ mkdir -p fsm/appendage && sudo chmod 0 fsm
$ node -e 'require("fs").stat("fsm/appendage",err=>console.log(err))'
{ Error: EACCES: permission denied, stat 'access/access' errno: -13, code: 'EACCES', syscall: 'stat', path: 'fsm/appendage' }
Zumindest wollen Sie:
let dir_exists = async path => {
let stat;
try {
stat = await (new Promise(
(resolve, reject) => require('fs').stat(path,
(err, result) => err ? reject(err) : resolve(result))
));
}
catch(e) {
if(e.code === 'ENOENT') return false;
throw e;
}
if(!stat.isDirectory())
throw new Error('Not a directory.');
return true;
};
Die Frage ist nicht klar, ob es tatsächlich synchron sein soll oder ob es nur so geschrieben werden soll, als ob es synchron wäre. In diesem Beispiel wird await / async verwendet, sodass es nur synchron geschrieben wird, aber asynchron ausgeführt wird.
Dies bedeutet, dass Sie es auf der obersten Ebene als solches bezeichnen müssen:
(async () => {
try {
console.log(await dir_exists('god'));
console.log(await dir_exists('fsm/appendage'));
}
catch(e) {
console.log(e);
}
})();
Eine Alternative ist die Verwendung von .then und .catch für das vom asynchronen Aufruf zurückgegebene Versprechen, wenn Sie es weiter unten benötigen.
Wenn Sie überprüfen möchten, ob etwas vorhanden ist, sollten Sie auch sicherstellen, dass es sich um die richtige Art von Dingen handelt, z. B. ein Verzeichnis oder eine Datei. Dies ist im Beispiel enthalten. Wenn es kein Symlink sein darf, müssen Sie lstat anstelle von stat verwenden, da stat automatisch Links durchläuft.
Sie können hier den gesamten asynchronen Code für die Synchronisierung ersetzen und stattdessen statSync verwenden. Erwarten Sie jedoch, dass die Synchronisierungsaufrufe, sobald Async und Warten allgemein unterstützt werden, überflüssig werden und schließlich abgeschrieben werden (andernfalls müssten Sie sie überall und in der Kette definieren, genau wie bei Async, was es wirklich sinnlos macht).