Jak sprawdzić istnienie pliku ?
W dokumentacji modułu fs
znajduje się opis metody fs.exists(path, callback)
. Ale, jak rozumiem, sprawdza, czy istnieją tylko katalogi. I muszę sprawdzić plik !
Jak to zrobić?
Jak sprawdzić istnienie pliku ?
W dokumentacji modułu fs
znajduje się opis metody fs.exists(path, callback)
. Ale, jak rozumiem, sprawdza, czy istnieją tylko katalogi. I muszę sprawdzić plik !
Jak to zrobić?
Odpowiedzi:
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.exists
i fs.exists
został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);
}
});
fs.exists
też działa. Miałem problemy z uprawnieniami do pliku.
path.exists
faktycznie jest przestarzały na korzyśćfs.exists
fs.exists
i fs.existsSync
również został uznany za przestarzały. Najlepszym sposobem sprawdzenia istnienia pliku jest fs.stat
pokazany powyżej.
fs.existsSync
nie jest już pozbawiony praw, chociaż fs.exists
nadal jest.
Łatwiejszy sposób na zrobienie tego synchronicznie.
if (fs.existsSync('/etc/file')) {
console.log('Found file');
}
Dokument API mówi, jak existsSync
działa:
sprawdź, czy podana ścieżka istnieje, sprawdzając w systemie plików.
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ź.
fs.existsSync
został wycofany, ale już nim nie jest.
Edycja:
Od węzła v10.0.0
moż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.log(´file 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;
}
fs.constants.F_OK
itp. Czy można również uzyskać do nich dostęp fs.F_OK
? Dziwne. Również zwięzłe, co jest miłe.
fs.promises.access(path, fs.constants.F_OK);
po prostu jako Obietnica zamiast tworzyć Obietnicę.
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.Stats
Zostanie 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.");
}
fs
pochodzi zmienna
fs.existsSync()
nie jest już przestarzały.
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
}
});
fs.exists
i fs.existsSync
są przestarzałe zgodnie z udostępnionym przez Ciebie linkiem.
existsSync
nie jest przestarzały zgodnie z tym dokumentem, może to być, gdy go czytałeś.
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
@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 )
Istnieje wiele niedokładnych komentarzy na temat fs.existsSync()
wycofania; nie jest.
https://nodejs.org/api/fs.html#fs_fs_existssync_path
Zauważ, że fs.exists () jest przestarzała, ale fs.existsSync () nie.
async/await
wersja używająca util.promisify
od 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);
}
});
});
Po krótkich eksperymentach stwierdziłem, że poniższy przykład fs.stat
jest 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ą reject
obietnicą samego błędu.
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?
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
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()
function fileExists(path, cb){
return new Promise((accept,deny) =>
fs.access(path, fs.constants.F_OK,(er, result)=> cb(!err && result))
);
}
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.
Możesz użyć fs.stat
do sprawdzenia, czy cel jest plikiem lub katalogiem i możesz użyć fs.access
do sprawdzenia, czy możesz zapisać / odczytać / wykonać plik. (pamiętaj, aby użyć, path.resolve
aby 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);
}());
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!
fs.access('file', err => err ? 'does not exist' : 'exists')
patrz fs.access