Se você estiver executando esta operação na inicialização ou inicialização do aplicativo, não há problema em bloquear a execução, pois você faria a mesma coisa se o fizesse de forma assíncrona. Se você estiver criando um diretório como uma operação recorrente, é uma prática ruim, mas provavelmente não causará nenhum problema de desempenho, mas é um hábito ruim, no entanto. Use apenas para inicializar seu aplicativo ou para operações únicas.
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á.
Como estamos falando de um diretório em vez de um arquivo, esse conselho implica que você deve ligar mkdire ignorar incondicionalmente EEXIST.
Em geral, você deve evitar os Syncmétodos * . Eles estão bloqueando, o que significa que absolutamente nada no seu programa pode acontecer enquanto você acessa o disco. Essa é uma operação muito cara e o tempo que leva para quebrar a suposição principal do loop de eventos do nó.
Os Syncmétodos * geralmente são bons em scripts rápidos de uso único (aqueles que fazem uma coisa e depois saem), mas quase nunca devem ser usados quando você está gravando um servidor: seu servidor não poderá responder a ninguém por todo o período dos pedidos de E / S. Se várias solicitações de clientes exigirem operações de E / S, o servidor será interrompido muito rapidamente.
A única vez em que eu consideraria o uso de Syncmétodos * em um aplicativo de servidor é em uma operação que acontece uma vez (e apenas uma vez), na inicialização. Por exemplo, requirena verdadereadFileSync , usa para carregar módulos.
Mesmo assim, você ainda precisa ter cuidado, pois muitas E / S síncronas podem diminuir desnecessariamente o tempo de inicialização do servidor.
Em vez disso, você deve usar os métodos de E / S assíncrona.
Portanto, se juntarmos esses conselhos, teremos algo assim:
function ensureExists(path, mask, cb){if(typeof mask =='function'){// allow the `mask` parameter to be optional
cb = mask;
mask =0777;}
fs.mkdir(path, mask,function(err){if(err){if(err.code =='EEXIST') cb(null);// ignore the error if the folder already existselse cb(err);// something else went wrong}else cb(null);// successfully created folder});}
E podemos usá-lo assim:
ensureExists(__dirname +'/upload',0744,function(err){if(err)// handle folder creation errorelse// we're all good});
Obviamente, isso não leva em conta casos extremos como
O que acontece se a pasta for excluída enquanto o programa estiver em execução? (supondo que você verifique apenas se existe uma vez durante a inicialização)
O que acontece se a pasta já existir, mas com as permissões erradas?
// Creates /tmp/a/apple, regardless of whether `/tmp` and /tmp/a exist.
fs.mkdir('/tmp/a/apple',{ recursive:true},(err)=>{if(err)throw err;});
NOTA: Você precisará importar o fsmódulo interno primeiro.
Agora, aqui está um exemplo um pouco mais robusto que aproveita os Módulos ES nativos (com sinalizador ativado e extensão .mjs), manipula caminhos não raiz e responde por nomes de caminho completos:
import fs from'fs';import path from'path';
createDirectories(pathname){const __dirname = path.resolve();
pathname = pathname.replace(/^\.*\/|\/?[^\/]+\.[a-z]+|\/$/g,'');// Remove leading directory markers, and remove ending /file-name.extension
fs.mkdir(path.resolve(__dirname, pathname),{ recursive:true}, e =>{if(e){
console.error(e);}else{
console.log('Success');}});}
Você pode usá-lo como createDirectories('/components/widget/widget.js');.
E, é claro, você provavelmente desejaria ter mais fantasia usando promessas com async / waitit para alavancar a criação de arquivos de uma maneira síncrona mais legível quando os diretórios forem criados; mas isso está além do escopo da pergunta.
Uma resposta tão subestimada! FS-extra tem bacame um deve ter para mim. Eu acho que é uma aberração escrever 10+ linhas apenas para verificar se existe uma pasta ...
538ROMEO
10
A melhor solução seria usar o módulo npm chamado node-fs-extra . Ele possui um método chamado mkdirque cria o diretório que você mencionou. Se você especificar um caminho de diretório longo, ele criará as pastas pai automaticamente. O módulo é um superconjunto de módulo npm fs, portanto, você pode usar todas as funções fstambém se adicionar este módulo.
Para o Node.js. v7.4.0, a documentação declara fs.exists()reprovado, mas fs.existsSync()não é. Você poderia adicionar um link a um recurso dizendo que fs.existsSync()está depreciado?
francis
1
As respostas somente de código não são muito úteis para os usuários que chegarem a essa pergunta no futuro. Edite sua resposta para explicar por que seu código resolve o problema original
var filessystem = require('fs');var dir ='./path/subpath/';if(!filessystem.existsSync(dir)){
filessystem.mkdirSync(dir);}else{
console.log("Directory already exist");}
const fs = require('fs')// in javascriptimport* as fs from"fs"// in typescriptimport fs from"fs"// in typescript// it will create the directory if it does not exist.!fs.existsSync(`./assets/`)&& fs.mkdirSync(`./assets/`,{ recursive:true})
import path from'path';import fs from'fs';(async()=>{const dir = path.join(__dirname,'upload');try{await fs.promises.mkdir(dir);}catch(error){if(error.code ==='EEXIST'){// Something already exists, but is it a file or directory?const lstat =await fs.promises.lstat(dir);if(!lstat.isDirectory()){throw error;}}else{throw error;}}})();
Você pode usar o comando Sistema de Arquivos do nó fs.stat para verificar se dir existe e fs.mkdir para criar um diretório com retorno de chamada ou fs.mkdirSync para criar um diretório sem retorno de chamada, como neste exemplo:
//first require fsconst fs = require('fs');// Create directory if not exist (function)const createDir =(path)=>{// check if dir exist
fs.stat(path,(err, stats)=>{if(stats.isDirectory()){// do nothing}else{// if the given path is not a directory, create a directory
fs.mkdirSync(path);}});};
Aqui está uma pequena função para criar diretórios recursivamente:
const createDir =(dir)=>{// This will create a dir given a path such as './folder/subfolder' const splitPath = dir.split('/');
splitPath.reduce((path, subPath)=>{let currentPath;if(subPath !='.'){
currentPath = path +'/'+ subPath;if(!fs.existsSync(currentPath)){
fs.mkdirSync(currentPath);}}else{
currentPath = subPath;}return currentPath
},'')}
Respostas:
fonte
Sync
métodos geralmente é um não-não: não queremos bloquear o ciclo de eventosNão, por várias razões.
O
path
módulo não possui um métodoexists
/existsSync
. Está nofs
módulo. (Talvez você tenha cometido um erro de digitação na sua pergunta?)Os documentos explicitamente o desencorajam de usar
exists
.Como estamos falando de um diretório em vez de um arquivo, esse conselho implica que você deve ligar
mkdir
e ignorar incondicionalmenteEEXIST
.Em geral, você deve evitar os
Sync
métodos * . Eles estão bloqueando, o que significa que absolutamente nada no seu programa pode acontecer enquanto você acessa o disco. Essa é uma operação muito cara e o tempo que leva para quebrar a suposição principal do loop de eventos do nó.Os
Sync
métodos * geralmente são bons em scripts rápidos de uso único (aqueles que fazem uma coisa e depois saem), mas quase nunca devem ser usados quando você está gravando um servidor: seu servidor não poderá responder a ninguém por todo o período dos pedidos de E / S. Se várias solicitações de clientes exigirem operações de E / S, o servidor será interrompido muito rapidamente.A única vez em que eu consideraria o uso de
Sync
métodos * em um aplicativo de servidor é em uma operação que acontece uma vez (e apenas uma vez), na inicialização. Por exemplo,require
na verdadereadFileSync
, usa para carregar módulos.Mesmo assim, você ainda precisa ter cuidado, pois muitas E / S síncronas podem diminuir desnecessariamente o tempo de inicialização do servidor.
Em vez disso, você deve usar os métodos de E / S assíncrona.
Portanto, se juntarmos esses conselhos, teremos algo assim:
E podemos usá-lo assim:
Obviamente, isso não leva em conta casos extremos como
fonte
0744 == 484
.Eu encontrei e módulo npm que funciona como um encanto para isso. É simplesmente fazer um mkdir recursivamente quando necessário, como um "mkdir -p".
https://www.npmjs.com/package/mkdirp
fonte
O
mkdir
método tem a capacidade de criar recursivamente todos os diretórios em um caminho que não existe e ignorar os que existem.Nos documentos do nó v10 / 11 :
NOTA: Você precisará importar o
fs
módulo interno primeiro.Agora, aqui está um exemplo um pouco mais robusto que aproveita os Módulos ES nativos (com sinalizador ativado e extensão .mjs), manipula caminhos não raiz e responde por nomes de caminho completos:
Você pode usá-lo como
createDirectories('/components/widget/widget.js');
.E, é claro, você provavelmente desejaria ter mais fantasia usando promessas com async / waitit para alavancar a criação de arquivos de uma maneira síncrona mais legível quando os diretórios forem criados; mas isso está além do escopo da pergunta.
fonte
Apenas no caso de alguém interessado na versão de uma linha. :)
fonte
Você pode simplesmente usar
mkdir
e capturar o erro se a pasta existir.Isso é assíncrono (portanto, é uma prática recomendada) e seguro.
(Opcionalmente, adicione um segundo argumento com o modo.)
Outros pensamentos:
Você pode usar ou aguardar usando o promisify nativo .
Você pode criar seu próprio método de promessa, algo como (não testado):
Para verificação síncrona, você pode usar:
Ou você pode usar uma biblioteca, as duas mais populares
fonte
mkdir('/path').catch(err => { if (err.code != 'EEXIST') throw err;}).then(myFunc);
!==
vez de!=
Com o pacote fs-extra , você pode fazer isso com uma linha :
fonte
A melhor solução seria usar o módulo npm chamado node-fs-extra . Ele possui um método chamado
mkdir
que cria o diretório que você mencionou. Se você especificar um caminho de diretório longo, ele criará as pastas pai automaticamente. O módulo é um superconjunto de módulo npmfs
, portanto, você pode usar todas as funçõesfs
também se adicionar este módulo.fonte
fonte
fs.exists()
reprovado, masfs.existsSync()
não é. Você poderia adicionar um link a um recurso dizendo quefs.existsSync()
está depreciado?Apr 2018
: nodejs.org/api/fs.html#fs_fs_existssync_pathIsso pode ajudá-lo :)
fonte
Solução
fonte
Gostaria de adicionar um refatorador de promessa de texto datilografado da resposta de josh3736 .
Ele faz a mesma coisa e tem os mesmos casos extremos, por acaso usa Promessas, typedefs datilografados e trabalha com "use strict".
fonte
Com o nó 10 + ES6:
fonte
Você pode usar o comando Sistema de Arquivos do nó fs.stat para verificar se dir existe e fs.mkdir para criar um diretório com retorno de chamada ou fs.mkdirSync para criar um diretório sem retorno de chamada, como neste exemplo:
fonte
Aqui está uma pequena função para criar diretórios recursivamente:
fonte
Usando assíncrono / espera:
Você precisará promisificar
fs
:fonte