Como posso verificar de forma síncrona, usando o node.js , se existe um arquivo ou diretório?
exists
adicionará apenas retornos de chamada desnecessários.
Como posso verificar de forma síncrona, usando o node.js , se existe um arquivo ou diretório?
exists
adicionará 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.access
se estiver usando async
funções ou fs.access
(já que exists
foi preterido ) se não:
Em uma async
funçã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
/ statSync
ou lstat
/ lstatSync
)exists
/ existsSync
)exists
/ existsSync
, portanto, provavelmente estamos de volta a stat
/ statSync
ou 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.stat
recomendar o uso fs.access
se 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 statSync
or lstatSync
( link do docs ), que fornece um fs.Stats
objeto . 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 Sync
no final. Assim statSync
é a versão síncrona de stat
; lstatSync
é a versão síncrona de lstat
etc.
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/catch
mas não fornece informações sobre o que é a coisa, apenas que está lá. path.existsSync
foi preterido há muito tempo.
Nota lateral: Você perguntou expressamente como verificar de forma síncrona ; portanto, usei as xyzSync
versõ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 lstat
vez 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.existsSync
para fazer uma verificação síncrona da existência de arquivo / diretório (ou, é claro, fs.exists
de uma verificação assíncrona), em vez das path
versõ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 stat
mé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.stat
documentação recomenda o uso fs.access
de 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.)
open
chamada 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.exists
e path.existsSync
agora estão obsoletos . Por favor, use .fs.exists
efs.existsSync
fs.exists
e foram preteridos . Use fs.stat () ou fs.access () .fs.existsSync
também
use fs.existsSync
. Não está obsoleto.
https://nodejs.org/api/fs.html#fs_fs_existssync_path
fs.existsSync
.
exists
função antiga :is-there
fs.exists
como obsoletos, enquanto fs.existsSync
nã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 filename
ou 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.exists
e fs.existsSync
estão obsoletas. De acordo com os documentos, isso não é mais verdade. Somente fs.exists
está 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 path
módulo não fornece uma versão síncrona, path.exists
então você precisa contornar o fs
módulo.
A coisa mais rápida que posso imaginar é usar o fs.realpathSync
que 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 await
palavra - 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).