Como posso verificar de forma síncrona, usando o node.js , se existe um arquivo ou diretório?
existsadicionará apenas retornos de chamada desnecessários.
Como posso verificar de forma síncrona, usando o node.js , se existe um arquivo ou diretório?
existsadicionará apenas retornos de chamada desnecessários.
Respostas:
A resposta a esta pergunta mudou ao longo dos anos. A resposta atual está aqui no topo, seguida pelas várias respostas ao longo dos anos em ordem cronológica:
Você pode usar fs.existsSync():
const fs = require("fs"); // Or `import fs from "fs";` with ESM
if (fs.existsSync(path)) {
// Do something
}
Foi preterido por vários anos, mas não é mais. Dos documentos:
Observe que
fs.exists()está obsoleto, masfs.existsSync()não está. (O parâmetro de retorno de chamada parafs.exists()aceita parâmetros inconsistentes com outros retornos de chamada do Node.js.fs.existsSync()não usa um retorno de chamada.)
Você solicitou especificamente uma verificação síncrona , mas se você pode usar uma verificação assíncrona (geralmente melhor com E / S), use fs.promises.accessse estiver usando asyncfunções ou fs.access(já que existsfoi preterido ) se não:
Em uma asyncfunção:
try {
await fs.promises.access("somefile");
// The check succeeded
} catch (error) {
// The check failed
}
Ou com um retorno de chamada:
fs.access("somefile", error => {
if (!error) {
// The check succeeded
} else {
// The check failed
}
});
Aqui estão as respostas históricas em ordem cronológica:
stat/ statSyncou lstat/ lstatSync)exists/ existsSync)exists/ existsSync, portanto, provavelmente estamos de volta a stat/ statSyncou lstat/ lstatSync)fs.access(path, fs.F_OK, function(){})/ fs.accessSync(path, fs.F_OK), mas observe que, se o arquivo / diretório não existir, será um erro; documentos para fs.statrecomendar o uso fs.accessse você precisar verificar a existência sem abrir)fs.exists() ainda está obsoleta, mas fs.existsSync()não está mais obsoleta. Então você pode usá-lo com segurança agora.Você pode usar statSyncor lstatSync( link do docs ), que fornece um fs.Statsobjeto . Em geral, se uma versão síncrona de uma função estiver disponível, ela terá o mesmo nome da versão assíncrona Syncno final. Assim statSyncé a versão síncrona de stat; lstatSyncé a versão síncrona de lstatetc.
lstatSync informa se existe algo e, em caso afirmativo, se é um arquivo ou um diretório (ou em alguns sistemas de arquivos, um link simbólico, um dispositivo de bloco, um dispositivo de caracteres etc.), por exemplo, se você precisa saber se existe ou não um diretório:
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) {
// ...
}
... e da mesma forma, se é um arquivo, existe isFile; se é um dispositivo de bloco, há isBlockDevice, etc., etc. Observe o try/catch; gera um erro se a entrada não existir.
Se você não se importa que a entrada é e só quero saber se ele existe, você pode usar path.existsSync(ou com o mais recente, fs.existsSync) como observado por user618408 :
var path = require('path');
if (path.existsSync("/the/path")) { // or fs.existsSync
// ...
}
Não requer um, try/catchmas não fornece informações sobre o que é a coisa, apenas que está lá. path.existsSyncfoi preterido há muito tempo.
Nota lateral: Você perguntou expressamente como verificar de forma síncrona ; portanto, usei as xyzSyncversões das funções acima. Mas sempre que possível, com E / S, é realmente melhor evitar chamadas síncronas. As chamadas para o subsistema de E / S levam um tempo significativo do ponto de vista da CPU. Observe como é fácil ligar em lstatvez de lstatSync:
// Is it a directory?
lstat('/the/path', function(err, stats) {
if (!err && stats.isDirectory()) {
// Yes it is
}
});
Mas se você precisar da versão síncrona, ela estará lá.
A resposta abaixo de alguns anos atrás agora está um pouco desatualizada. A maneira atual é usar fs.existsSyncpara fazer uma verificação síncrona da existência de arquivo / diretório (ou, é claro, fs.existsde uma verificação assíncrona), em vez das pathversões abaixo.
Exemplo:
var fs = require('fs');
if (fs.existsSync(path)) {
// Do something
}
// Or
fs.exists(path, function(exists) {
if (exists) {
// Do something
}
});
E aqui estamos em 2015 e os documentos do Node agora dizem que fs.existsSync(e fs.exists) "será preterido". (Como o pessoal do Nó acha que é estúpido verificar se existe algo antes de abri-lo, qual é; mas esse não é o único motivo para verificar se existe algo!)
Então, provavelmente estamos de volta aos vários statmétodos ... Até / a menos que isso mude novamente, é claro.
Não sei há quanto tempo está lá, mas também há fs.access(path, fs.F_OK, ...)/fs.accessSync(path, fs.F_OK) . E, pelo menos a partir de outubro de 2016, a fs.statdocumentação recomenda o uso fs.accessde verificações de existência ( "Para verificar se existe um arquivo sem manipulá-lo posteriormente, fs.access()é recomendável." ). Mas observe que o acesso não disponível é considerado um erro ; portanto, provavelmente seria melhor se você espera que o arquivo seja acessível:
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
}
});
Você pode usar fs.existsSync():
if (fs.existsSync(path)) {
// Do something
}
Foi preterido por vários anos, mas não é mais. Dos documentos:
Observe que
fs.exists()está obsoleto, masfs.existsSync()não está. (O parâmetro de retorno de chamada parafs.exists()aceita parâmetros inconsistentes com outros retornos de chamada do Node.js.fs.existsSync()não usa um retorno de chamada.)
openchamada e manipular a exceção ou o que quer que seja, se o arquivo não estiver disponível. encontrado. Afinal, o mundo real é caótico: se você verificar primeiro e ele estiver lá, isso não significa que ainda estará lá quando você tentar abri-lo; se você verificar primeiro e ele não estiver lá, isso não significa que não estará lá um momento depois. Cronometrar coisas assim parecem casos extremos, mas surgem o tempo todo . Portanto, se você for abrir, não adianta verificar primeiro.
Olhando a fonte, há uma versão síncrona de path.exists- path.existsSync. Parece que foi esquecido nos documentos.
path.existse path.existsSyncagora estão obsoletos . Por favor, use .fs.existsefs.existsSync
fs.exists e foram preteridos . Use fs.stat () ou fs.access () .fs.existsSynctambém
use fs.existsSync. Não está obsoleto.
https://nodejs.org/api/fs.html#fs_fs_existssync_path
fs.existsSync.
existsfunção antiga :is-there
fs.existscomo obsoletos, enquanto fs.existsSyncnão são!
Usando as APIs atualmente recomendadas (a partir de 2015) (de acordo com os documentos do Node), é isso que eu faço:
var fs = require('fs');
function fileExists(filePath)
{
try
{
return fs.statSync(filePath).isFile();
}
catch (err)
{
return false;
}
}
Em resposta à questão EPERM levantada pela @broadband nos comentários, isso traz um bom argumento. fileExists () provavelmente não é uma boa maneira de pensar sobre isso em muitos casos, porque fileExists () não pode realmente prometer um retorno booleano. Você pode determinar definitivamente se o arquivo existe ou não, mas também pode receber um erro de permissão. O erro de permissão não implica necessariamente que o arquivo existe, porque você pode não ter permissão para o diretório que contém o arquivo no qual está verificando. E, é claro, há a chance de você encontrar outro erro ao verificar a existência do arquivo.
Portanto, meu código acima é realmente doesFileExistAndDoIHaveAccessToIt (), mas sua pergunta pode ser doesFileNotExistAndCouldICreateIt (), que seria uma lógica completamente diferente (que precisaria ser responsável por um erro EPERM, entre outras coisas).
Embora a resposta fs.existsSync atenda diretamente à pergunta feita aqui, isso geralmente não será o que você deseja (você não quer apenas saber se "algo" existe no caminho), provavelmente se preocupa se a "coisa" existe um arquivo ou diretório).
A conclusão é que, se você está verificando se existe um arquivo, provavelmente está fazendo isso porque pretende tomar alguma ação com base no resultado, e essa lógica (a verificação e / ou a ação subsequente) deve acomodar a ideia que algo encontrado nesse caminho pode ser um arquivo ou um diretório e que você pode encontrar o EPERM ou outros erros no processo de verificação.
file.exists()utilitário simples para os 3% e nos forçará a envolvê-lo em uma tentativa de captura? Caia na real ... Vadia do dia.
Outra atualização
Precisando de uma resposta para esta pergunta eu mesmo, procurei os documentos do nó, parece que você não deveria estar usando o fs.exists, em vez disso, use o fs.open e use o erro gerado para detectar se um arquivo não existe:
dos documentos:
fs.exists () é um anacronismo e existe apenas por razões históricas. Quase nunca deve haver um motivo para usá-lo em seu próprio código.
Em particular, verificar se um arquivo existe antes de abri-lo é um antipadrão que o deixa vulnerável às condições de corrida: outro processo pode remover o arquivo entre as chamadas para fs.exists () e fs.open (). Basta abrir o arquivo e manipular o erro quando ele não estiver lá.
Eu uso a função abaixo para testar se o arquivo existe. Também pega outras exceções. Portanto, caso haja problemas de direitos, por exemplo, chmod ugo-rwx filenameou na Right Click -> Properties -> Security -> Advanced -> Permission entries: empty list ..função Windows
, a exceção retornará como deveria. O arquivo existe, mas não temos direitos para acessá-lo. Seria errado ignorar esse tipo de exceção.
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, ...
}
}
Saída de exceção, documentação de erros do nodejs no caso de o arquivo não existir:
{
[Error: ENOENT: no such file or directory, stat 'X:\\delsdfsdf.txt']
errno: -4058,
code: 'ENOENT',
syscall: 'stat',
path: 'X:\\delsdfsdf.txt'
}
Exceção no caso de não termos direitos sobre o arquivo, mas existe:
{
[Error: EPERM: operation not permitted, stat 'X:\file.txt']
errno: -4048,
code: 'EPERM',
syscall: 'stat',
path: 'X:\\file.txt'
}
fs.exists () está obsoleto, não o use https://nodejs.org/api/fs.html#fs_fs_exists_path_callback
Você pode implementar a maneira principal do nodejs usada desta maneira: 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;
}
isso retornará o objeto de estatísticas e, depois de obter o objeto de estatísticas, você poderá tentar
var exist = statPath('/path/to/your/file.js');
if(exist && exist.isFile()) {
// do something
}
Algumas respostas aqui dizem isso fs.existse fs.existsSyncestão obsoletas. De acordo com os documentos, isso não é mais verdade. Somente fs.existsestá depreciado agora:
Observe que fs.exists () está obsoleto, mas fs.existsSync () não está. (O parâmetro de retorno de chamada para fs.exists () aceita parâmetros inconsistentes com outros retornos de chamada do Node.js. fs.existsSync () não usa um retorno de chamada.)
Portanto, você pode usar com segurança o fs.existsSync () para verificar de forma síncrona se existe um arquivo.
O pathmódulo não fornece uma versão síncrona, path.existsentão você precisa contornar o fsmódulo.
A coisa mais rápida que posso imaginar é usar o fs.realpathSyncque lançará um erro que você deve capturar; portanto, você precisa fazer seu próprio wrapper funcionar com uma tentativa / captura.
O uso de testes fileSystem (fs) acionará objetos de erro, que você precisará agrupar em uma instrução try / catch. Economize um pouco de esforço e use um recurso apresentado na ramificação 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);
});
});
Os documentos fs.stat()dizem para usar fs.access()se você não for manipular o arquivo. Não deu uma justificativa, pode ser mais rápido ou menos uso de memórias?
Eu uso o nó para automação linear, então pensei em compartilhar a função que utilizo para testar a existência de arquivos.
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;
}
atualizado como resposta para as pessoas 'corretamente', indicando que não responde diretamente à pergunta, mais traz uma opção alternativa.
fs.existsSync('filePath')veja também documentos aqui .
Retorna true se o caminho existir, false caso contrário.
Em um contexto assíncrono, você pode simplesmente escrever a versão assíncrona no método sync usando a awaitpalavra - chave Você pode simplesmente transformar o método de retorno de chamada assíncrona em uma promessa como esta:
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');
}
}
os documentos sobre 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); }, ); }); }
As chances são de que, se você quiser saber se existe um arquivo, planeja solicitá-lo, se existir.
function getFile(path){
try{
return require(path);
}catch(e){
return false;
}
}
Aqui está uma solução de wrapper simples para isso:
var fs = require('fs')
function getFileRealPath(s){
try {return fs.realpathSync(s);} catch(e){return false;}
}
Uso:
Exemplo:
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);
}
Certifique-se de usar o operador === para testar se o retorno é falso. Não há razão lógica para que fs.realpathSync () retorne false em condições de trabalho adequadas, portanto, acho que isso deve funcionar 100%.
Eu preferiria ver uma solução que não gera um erro e um resultado resultante. Da perspectiva da API, fs.exists () parece ser a solução mais elegante.
A partir das respostas, parece que não há suporte oficial da API para isso (como em uma verificação direta e explícita). Muitas das respostas dizem usar stat, no entanto, não são rigorosas. Não podemos assumir, por exemplo, que qualquer erro gerado por stat signifique que algo não existe.
Vamos dizer que tentamos com algo que não existe:
$ 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' }
Vamos tentar com algo que existe, mas que não temos acesso a:
$ 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' }
No mínimo, você deseja:
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;
};
A questão não está clara se você realmente deseja que seja síncrono ou se apenas deseja que seja escrito como se fosse síncrono. Este exemplo usa aguardar / assíncrono para que ele seja gravado apenas de maneira sincronizada, mas seja executado de forma assíncrona.
Isso significa que você deve chamá-lo como tal no nível superior:
(async () => {
try {
console.log(await dir_exists('god'));
console.log(await dir_exists('fsm/appendage'));
}
catch(e) {
console.log(e);
}
})();
Uma alternativa é usar .then e .catch na promessa retornada da chamada assíncrona, se você precisar mais.
Se você deseja verificar se algo existe, é uma boa prática também garantir que seja o tipo certo de coisa, como um diretório ou arquivo. Isso está incluído no exemplo. Se não for permitido que seja um link simbólico, você deve usar lstat em vez de stat, pois o stat atravessará automaticamente os links.
Você pode substituir todo o código assíncrono para sincronizar aqui e usar o statSync. No entanto, espere que, uma vez que o assíncrono e o aguardar se tornem universalmente compatíveis, as chamadas de sincronização se tornarão redundantes para serem depreciadas (caso contrário, você teria que defini-las em todos os lugares e na cadeia, assim como com o assíncrono, tornando-o realmente inútil).