Jak mogę synchronicznie sprawdzić za pomocą node.js , czy plik lub katalog istnieje?
exists
po prostu dodaje niepotrzebne wywołania zwrotne.
Jak mogę synchronicznie sprawdzić za pomocą node.js , czy plik lub katalog istnieje?
exists
po prostu dodaje niepotrzebne wywołania zwrotne.
Odpowiedzi:
Odpowiedź na to pytanie zmieniała się na przestrzeni lat. prąd Odpowiedź jest tutaj na górze, a następnie przez różne odpowiedzi przez lata w porządku chronologicznym:
Możesz użyć fs.existsSync()
:
const fs = require("fs"); // Or `import fs from "fs";` with ESM
if (fs.existsSync(path)) {
// Do something
}
Był przestarzały przez kilka lat, ale już nie jest. Z dokumentów:
Pamiętaj, że
fs.exists()
jest przestarzałe, alefs.existsSync()
nie jest. (Parametr wywołania zwrotnegofs.exists()
akceptuje parametry niezgodne z innymi wywołaniami zwrotnymi Node.js.fs.existsSync()
Nie używa wywołania zwrotnego.)
W szczególności poprosiłeś o sprawdzenie synchroniczne , ale jeśli zamiast tego możesz użyć sprawdzenia asynchronicznego (zwykle najlepiej z I / O), użyj, fs.promises.access
jeśli używasz async
funkcji lub fs.access
(ponieważ exists
jest przestarzałe ), jeśli nie:
W async
funkcji:
try {
await fs.promises.access("somefile");
// The check succeeded
} catch (error) {
// The check failed
}
Lub z oddzwanianiem:
fs.access("somefile", error => {
if (!error) {
// The check succeeded
} else {
// The check failed
}
});
Oto odpowiedzi historyczne w kolejności chronologicznej:
stat
/ statSync
lub lstat
/ lstatSync
)exists
/ existsSync
)exists
/ existsSync
, więc prawdopodobnie wróciliśmy do stat
/ statSync
lub lstat
/ lstatSync
)fs.access(path, fs.F_OK, function(){})
/ fs.accessSync(path, fs.F_OK)
, ale zwróć uwagę, że jeśli plik / katalog nie istnieje, jest to błąd; fs.stat
zaleca się korzystanie z dokumentów, fs.access
jeśli chcesz sprawdzić istnienie bez otwierania)fs.exists()
Jest nadal przestarzała, ale fs.existsSync()
nie jest już przestarzała. Możesz teraz bezpiecznie z niego korzystać.Możesz użyć statSync
lub lstatSync
( link do dokumentu ), który daje ci fs.Stats
obiekt . Zasadniczo, jeśli dostępna jest synchroniczna wersja funkcji, będzie miała taką samą nazwę jak wersja asynchroniczna Sync
na końcu. Podobnie statSync
jest z synchroniczną wersją stat
; lstatSync
jest wersją synchroniczną lstat
itp.
lstatSync
mówi zarówno, czy coś istnieje, a jeśli tak, to czy jest to plik, czy katalog (lub w niektórych systemach plików, dowiązanie symboliczne, urządzenie blokowe, urządzenie znakowe itp.), np. czy musisz wiedzieć, czy istnieje i czy jest katalog:
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) {
// ...
}
... i podobnie, jeśli jest to plik, istnieje isFile
; jeśli jest to urządzenie blokowe, istnieje isBlockDevice
itp. itd. Uwaga try/catch
; zgłasza błąd, jeśli pozycja w ogóle nie istnieje.
Jeśli nie obchodzi Cię, czym jest wpis i chcesz tylko wiedzieć, czy istnieje, możesz użyć path.existsSync
(lub najnowszej wersji fs.existsSync
), jak zauważył użytkownik 618408 :
var path = require('path');
if (path.existsSync("/the/path")) { // or fs.existsSync
// ...
}
Nie wymaga, try/catch
ale nie daje żadnych informacji o tym, co to jest, po prostu to, że tam jest. path.existsSync
został wycofany dawno temu.
Uwaga dodatkowa: wyraźnie zapytałeś, jak sprawdzać synchronicznie , więc użyłem xyzSync
powyższych wersji funkcji. Ale tam, gdzie to możliwe, we / wy naprawdę najlepiej unikać połączeń synchronicznych. Wywołania do podsystemu we / wy zajmują dużo czasu z punktu widzenia procesora. Zwróć uwagę, jak łatwo jest zadzwonić, lstat
a nie lstatSync
:
// Is it a directory?
lstat('/the/path', function(err, stats) {
if (!err && stats.isDirectory()) {
// Yes it is
}
});
Ale jeśli potrzebujesz wersji synchronicznej, jest ona dostępna.
Poniższa odpowiedź sprzed kilku lat jest teraz trochę nieaktualna. Obecny sposób polega na fs.existsSync
przeprowadzeniu synchronicznego sprawdzania istnienia pliku / katalogu (lub oczywiście fs.exists
na sprawdzeniu asynchronicznym) zamiast napath
poniższych wersjach.
Przykład:
var fs = require('fs');
if (fs.existsSync(path)) {
// Do something
}
// Or
fs.exists(path, function(exists) {
if (exists) {
// Do something
}
});
I oto jesteśmy w 2015 roku, a dokumenty Node mówią teraz fs.existsSync
(ifs.exists
) „będą przestarzałe”. (Ponieważ ludzie z Węzła uważają, że głupio jest sprawdzać, czy coś istnieje przed otwarciem, co to jest; ale to nie jedyny powód, aby sprawdzić, czy coś istnieje!)
Więc prawdopodobnie wróciliśmy do różnych stat
metod ... Aż / chyba, że to się zmieni jeszcze raz, oczywiście.
Nie wiem, jak długo tam był, ale jest też fs.access(path, fs.F_OK, ...)
/fs.accessSync(path, fs.F_OK)
. Przynajmniej w październiku 2016 r. fs.stat
Dokumentacja zaleca używanie fs.access
do sprawdzania istnienia ( zalecane jest „sprawdzenie, czy plik istnieje bez manipulowania nim później fs.access()
” ). Pamiętaj jednak, że brak dostępu jest uważany za błąd , więc prawdopodobnie byłoby to najlepsze, jeśli spodziewasz się, że plik będzie dostępny:
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
}
});
Możesz użyć fs.existsSync()
:
if (fs.existsSync(path)) {
// Do something
}
Był przestarzały przez kilka lat, ale już nie jest. Z dokumentów:
Pamiętaj, że
fs.exists()
jest przestarzałe, alefs.existsSync()
nie jest. (Parametr wywołania zwrotnegofs.exists()
akceptuje parametry niezgodne z innymi wywołaniami zwrotnymi Node.js.fs.existsSync()
Nie używa wywołania zwrotnego.)
open
wywołać połączenie i obsłużyć wyjątek lub cokolwiek, jeśli plik nie był znaleziony. W końcu prawdziwy świat jest chaotyczny: jeśli najpierw sprawdzisz i już tam jest, to nie znaczy, że będzie tam nadal, gdy spróbujesz go otworzyć; jeśli najpierw sprawdzisz, a go nie ma, to nie znaczy, że nie będzie go ani chwili później. Takie rzeczy w taktach wydają się być przypadkami na krawędzi, ale pojawiają się cały czas . Więc jeśli zamierzasz otworzyć, nie ma sensu sprawdzać najpierw.
Patrząc na źródło, istnieje synchroniczna wersja path.exists
- path.existsSync
. Wygląda na to, że zgubił się w dokumentacji.
path.exists
i path.existsSync
są teraz przestarzałe . Proszę użyć .fs.exists
ifs.existsSync
fs.exists
i zostały wycofane . Zamiast tego użyj fs.stat () lub fs.access () .fs.existsSync
również
użyć fs.existsSync
. To nie jest przestarzałe.
https://nodejs.org/api/fs.html#fs_fs_existssync_path
fs.existsSync
.
exists
funkcję:is-there
fs.exists
jako przestarzałe, a fs.existsSync
nie jest!
Korzystając z obecnie zalecanych (od 2015 r.) Interfejsów API (według dokumentów węzła), robię to:
var fs = require('fs');
function fileExists(filePath)
{
try
{
return fs.statSync(filePath).isFile();
}
catch (err)
{
return false;
}
}
W odpowiedzi na kwestię EPERM podniesioną przez @broadband w komentarzach, porusza to dobry punkt. fileExists () prawdopodobnie nie jest dobrym sposobem na przemyślenie tego w wielu przypadkach, ponieważ fileExists () nie może tak naprawdę obiecać zwrotu logicznego. Możesz być w stanie definitywnie ustalić, że plik istnieje lub nie istnieje, ale możesz również otrzymać błąd uprawnień. Błąd uprawnień niekoniecznie oznacza, że plik istnieje, ponieważ może brakować uprawnień do katalogu zawierającego plik, który sprawdzasz. I oczywiście istnieje szansa, że napotkasz inny błąd w sprawdzaniu istnienia pliku.
Tak więc mój powyższy kod to tak naprawdę robiFileExistAndDoIHaveAccessToIt (), ale twoim pytaniem może być doesFileNotExistAndCouldICreateIt (), co byłoby zupełnie inną logiką (która musiałaby uwzględniać między innymi błąd EPERM).
Podczas gdy odpowiedź fs.existsSync odnosi się bezpośrednio do pytania zadanego tutaj, często nie jest to, czego chcesz (nie chcesz tylko wiedzieć, czy „coś” istnieje na ścieżce, prawdopodobnie zależy ci na tym, czy „rzecz” istnieje plik lub katalog).
Najważniejsze jest to, że jeśli sprawdzasz, czy plik istnieje, prawdopodobnie robisz to, ponieważ zamierzasz podjąć pewne działania w oparciu o wynik, a ta logika (sprawdzenie i / lub kolejne działanie) powinna uwzględniać pomysł że rzecz znaleziona w tej ścieżce może być plikiem lub katalogiem i że podczas sprawdzania możesz napotkać EPERM lub inne błędy.
file.exists()
dla 3% i zamiast tego zmuszasz nas do zawinięcia tego w try catch? Zyskaj prawdziwy ... Dziwka dnia.
Kolejna aktualizacja
Konieczności odpowiedzi na to pytanie sobie, spojrzał w górę docs węzła zdaje należy nie używać fs.exists, zamiast używać fs.open i używać outputted błąd wykryć, jeśli plik nie istnieje:
z dokumentów:
fs.exists () jest anachronizmem i istnieje tylko z powodów historycznych. Prawie nigdy nie powinno być powodu, aby używać go we własnym kodzie.
W szczególności sprawdzenie, czy plik istnieje przed otwarciem, jest anty-wzorcem, który naraża cię na warunki wyścigu: inny proces może usunąć plik między wywołaniami fs.exists () i fs.open (). Wystarczy otworzyć plik i obsłużyć błąd, gdy go nie ma.
Używam funkcji poniżej, aby sprawdzić, czy plik istnieje. Łapie także inne wyjątki. Więc w przypadku problemów z prawami np. chmod ugo-rwx filename
Lub w Right Click -> Properties -> Security -> Advanced -> Permission entries: empty list ..
funkcji Windows
zwraca wyjątek tak jak powinien. Plik istnieje, ale nie mamy prawa dostępu do niego. Błędem byłoby ignorowanie tego rodzaju wyjątków.
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, ...
}
}
Wyjście wyjątku, dokumentacja błędów nodejs w przypadku, gdy plik nie istnieje:
{
[Error: ENOENT: no such file or directory, stat 'X:\\delsdfsdf.txt']
errno: -4058,
code: 'ENOENT',
syscall: 'stat',
path: 'X:\\delsdfsdf.txt'
}
Wyjątek w przypadku, gdy nie mamy uprawnień do pliku, ale istnieje:
{
[Error: EPERM: operation not permitted, stat 'X:\file.txt']
errno: -4048,
code: 'EPERM',
syscall: 'stat',
path: 'X:\\file.txt'
}
fs.exists () jest przestarzałe, nie używaj go https://nodejs.org/api/fs.html#fs_fs_exists_path_callback
Możesz zaimplementować podstawową metodę nodejs zastosowaną w tym miejscu: 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;
}
to zwróci obiekt statystyki, a kiedy już dostaniesz obiekt statystyki, możesz spróbować
var exist = statPath('/path/to/your/file.js');
if(exist && exist.isFile()) {
// do something
}
Niektóre odpowiedzi tutaj mówią to fs.exists
i fs.existsSync
oba są przestarzałe. Według dokumentów nie jest to już prawdą. Tylko fs.exists
jest teraz usunięty:
Zauważ, że fs.exists () jest przestarzała, ale fs.existsSync () nie jest. (Parametr wywołania zwrotnego do fs.exists () akceptuje parametry niespójne z innymi wywołaniami zwrotnymi Node.js. Fs.existsSync () nie używa wywołania zwrotnego).
Możesz więc bezpiecznie używać fs.existsSync () do synchronicznego sprawdzania, czy plik istnieje.
path
Moduł nie zapewnia synchroniczną wersję path.exists
więc trzeba oszukać wokół zfs
modułu.
Najszybszą rzeczą, jaką mogę sobie wyobrazić, jest fs.realpathSync
rzucanie błędu, który musisz złapać, więc musisz stworzyć własną funkcję otoki za pomocą try / catch.
Testy fileSystem (fs) wyzwalają obiekty błędów, które następnie należy zawinąć w instrukcji try / catch. Zaoszczędź trochę wysiłku i skorzystaj z funkcji wprowadzonej w gałęzi 0.4.x.
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);
});
});
Dokumenty fs.stat()
mówią, że należy użyć, fs.access()
jeśli nie zamierzasz manipulować plikiem. Nie podało uzasadnienia, może być szybsze lub mniej użyteczne w pamięci?
Używam węzła do automatyzacji liniowej, więc pomyślałem, że dzielę funkcję, której używam do testowania istnienia pliku.
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;
}
zaktualizowany asnwer dla tych osób „poprawnie”, wskazując, że nie odpowiada bezpośrednio na pytanie, więcej oferuje alternatywną opcję.
fs.existsSync('filePath')
zobacz także dokumenty tutaj .
Zwraca true, jeśli ścieżka istnieje, w przeciwnym razie false.
W kontekście asynchronicznym można po prostu napisać wersję asynchroniczną metodą synchronizacji za pomocą await
słowa kluczowego. Możesz po prostu zmienić metodę wywołania zwrotnego asynchronicznego w taką obietnicę:
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');
}
}
dokumenty dotyczące dostępu ().
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); }, ); }); }
Możliwe, że jeśli chcesz wiedzieć, czy plik istnieje, planujesz go wymagać, jeśli tak jest.
function getFile(path){
try{
return require(path);
}catch(e){
return false;
}
}
Oto proste rozwiązanie tego opakowania:
var fs = require('fs')
function getFileRealPath(s){
try {return fs.realpathSync(s);} catch(e){return false;}
}
Stosowanie:
Przykład:
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);
}
Upewnij się, że używasz operatora ===, aby sprawdzić, czy return jest równe false. Nie ma żadnego logicznego powodu, aby fs.realpathSync () zwrócił false w odpowiednich warunkach pracy, więc myślę, że powinno to działać w 100%.
Wolałbym zobaczyć rozwiązanie, które nie generuje błędu i wynikowego spadku wydajności. Z perspektywy API fs.exists () wydaje się być najbardziej eleganckim rozwiązaniem.
Z odpowiedzi wynika, że nie ma w tym celu oficjalnego wsparcia API (jak w przypadku bezpośredniej i wyraźnej kontroli). Wiele odpowiedzi mówi, że używa statystyki, jednak nie są one ścisłe. Nie możemy na przykład założyć, że jakikolwiek błąd zgłoszony przez stat oznacza, że coś nie istnieje.
Powiedzmy, że próbujemy z czymś, co nie istnieje:
$ 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' }
Spróbujmy z czymś, co istnieje, ale nie mamy dostępu do:
$ 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' }
Przynajmniej będziesz chciał:
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;
};
Pytanie nie jest jasne, czy rzeczywiście chcesz, aby było synchroniczne, czy też chcesz, aby było napisane tak, jakby było synchroniczne. W tym przykładzie użyto funkcji Oczekiwanie / Async, dzięki czemu jest zapisywane tylko synchronicznie, ale działa asynchronicznie.
Oznacza to, że musisz tak to nazwać na najwyższym poziomie:
(async () => {
try {
console.log(await dir_exists('god'));
console.log(await dir_exists('fsm/appendage'));
}
catch(e) {
console.log(e);
}
})();
Alternatywą jest użycie .then i .catch na obietnicy zwróconej z wywołania asynchronicznego, jeśli jest ona potrzebna dalej.
Jeśli chcesz sprawdzić, czy coś istnieje, dobrą praktyką jest również upewnienie się, że jest to właściwy typ rzeczy, np. Katalog lub plik. Jest to uwzględnione w przykładzie. Jeśli nie jest to dowiązanie symboliczne, musisz użyć lstat zamiast stat, ponieważ stat automatycznie przejdzie przez linki.
Możesz zastąpić cały asynchroniczny kod, aby zsynchronizować kod tutaj i zamiast tego użyć statSync. Spodziewaj się jednak, że gdy asynchronizacja i oczekiwanie staną się uniwersalne, połączenia synchronizacji staną się w końcu zbędne, aby zostać zdeprecjonowane (w przeciwnym razie będziesz musiał zdefiniować je wszędzie i wyżej, tak jak w przypadku asynchronizacji, co czyni je naprawdę bezcelowymi).