Czy to właściwy sposób na utworzenie katalogu, jeśli nie istnieje. Powinien mieć pełne pozwolenie na skrypt i być czytelny dla innych.
var dir = __dirname + '/upload';
if (!path.existsSync(dir)) {
fs.mkdirSync(dir, 0744);
}
Czy to właściwy sposób na utworzenie katalogu, jeśli nie istnieje. Powinien mieć pełne pozwolenie na skrypt i być czytelny dla innych.
var dir = __dirname + '/upload';
if (!path.existsSync(dir)) {
fs.mkdirSync(dir, 0744);
}
Odpowiedzi:
var fs = require('fs');
var dir = './tmp';
if (!fs.existsSync(dir)){
fs.mkdirSync(dir);
}
Syncmetod jest zwykle nie-nie: nie chcę blokować pętli zdarzeń
Nie, z wielu powodów.
pathModuł nie ma exists/ existsSyncmetody. Jest w fsmodule. (Być może właśnie napisałeś literówkę w swoim pytaniu?)
Dokumenty wyraźnie zniechęcają do korzystania exists.
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 do
fs.exists()ifs.open(). Wystarczy otworzyć plik i obsłużyć błąd, gdy go nie ma.
Ponieważ mówimy raczej o katalogu niż pliku, ta rada sugeruje, że powinieneś bezwarunkowo zadzwonić mkdiri zignorować EEXIST.
Ogólnie powinieneś unikać * Syncmetod. Blokują, co oznacza, że absolutnie nic innego w twoim programie nie może się zdarzyć podczas przechodzenia na dysk. Jest to bardzo kosztowna operacja, a czas potrzebny na złamanie podstawowego założenia pętli zdarzeń węzła.
SyncMetody * są zwykle dobre w szybkich skryptach jednofunkcyjnych (tych, które wykonują jedną rzecz, a następnie wychodzą), ale prawie nigdy nie powinny być używane podczas pisania serwera: serwer nie będzie w stanie odpowiedzieć nikomu przez cały czas trwania żądań We / Wy. Jeśli wiele żądań klientów wymaga operacji we / wy, serwer bardzo szybko się zatrzyma.
Jedynym momentem, w którym rozważę użycie * Syncmetod w aplikacji serwera, jest operacja, która dzieje się raz (i tylko raz) przy uruchomieniu. Na przykład require faktycznie używareadFileSync do ładowania modułów.
Nawet wtedy musisz zachować ostrożność, ponieważ wiele synchronicznych operacji we / wy może niepotrzebnie spowalniać czas uruchamiania serwera.
Zamiast tego należy użyć asynchronicznych metod we / wy.
Jeśli więc zbierzemy te porady, otrzymamy coś takiego:
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 exists
else cb(err); // something else went wrong
} else cb(null); // successfully created folder
});
}
I możemy użyć tego w następujący sposób:
ensureExists(__dirname + '/upload', 0744, function(err) {
if (err) // handle folder creation error
else // we're all good
});
Oczywiście nie uwzględnia to przypadków typu edge
0744 == 484.
Znalazłem i moduł npm, który działa do tego jak urok. Po prostu wykonaj rekursywnie mkdir w razie potrzeby, na przykład „mkdir -p”.
mkdirMetoda ma zdolność do rekursywnie utworzyć żadnych katalogów w ścieżce, które nie istnieją, i ignorować te, które wykonują.
Z dokumentów Node v10 / 11 :
// Creates /tmp/a/apple, regardless of whether `/tmp` and /tmp/a exist.
fs.mkdir('/tmp/a/apple', { recursive: true }, (err) => {
if (err) throw err;
});
UWAGA: Musisz zaimportować wbudowany fs Najpierw moduł.
Oto trochę bardziej solidny przykład, który wykorzystuje natywne moduły ES (z włączoną flagą i rozszerzeniem .mjs), obsługuje ścieżki inne niż root i uwzględnia pełne nazwy ścieżek:
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');
}
});
}
Możesz go używać jak createDirectories('/components/widget/widget.js');.
I oczywiście, prawdopodobnie chciałbyś zyskać więcej fantazji, używając obietnic z asynchronizacją / czekaj, aby wykorzystać tworzenie plików w bardziej czytelny, synchroniczny sposób podczas tworzenia katalogów; ale to wykracza poza zakres pytania.
Na wszelki wypadek zainteresowany wersją jednoliniową. :)
//or in typescript: import * as fs from 'fs';
const fs = require('fs');
!fs.existsSync(dir) && fs.mkdirSync(dir);
Możesz po prostu użyć mkdiri złapać błąd, jeśli folder istnieje.
Jest to asynchroniczne (więc najlepsza praktyka) i bezpieczne.
fs.mkdir('/path', err => {
if (err && err.code != 'EEXIST') throw 'up'
.. safely do your stuff here
})
(Opcjonalnie dodaj drugi argument do trybu).
Inne przemyślenia:
Możesz wtedy użyć lub poczekać, używając natywnego promisify .
const util = require('util'), fs = require('fs');
const mkdir = util.promisify(fs.mkdir);
var myFunc = () => { ..do something.. }
mkdir('/path')
.then(myFunc)
.catch(err => { if (err.code != 'EEXIST') throw err; myFunc() })Możesz stworzyć własną metodę obietnicy, taką jak (niesprawdzona):
let mkdirAsync = (path, mode) => new Promise(
(resolve, reject) => mkdir (path, mode,
err => (err && err.code !== 'EEXIST') ? reject(err) : resolve()
)
)Do sprawdzania synchronicznego możesz użyć:
fs.existsSync(path) || fs.mkdirSync(path)Możesz też skorzystać z biblioteki, z której dwie są najbardziej popularne
mkdir('/path').catch(err => { if (err.code != 'EEXIST') throw err;}).then(myFunc);
!==zamiast!=
Dzięki pakietowi fs-extra możesz to zrobić za pomocą jednej linijki :
const fs = require('fs-extra');
const dir = '/tmp/this/path/does/not/exist';
fs.ensureDirSync(dir);
Najlepszym rozwiązaniem byłoby użycie modułu npm o nazwie node-fs-extra . Ma metodę o nazwie, mkdirktóra tworzy wspomniany katalog. Jeśli podasz długą ścieżkę do katalogu, automatycznie utworzy ona foldery nadrzędne. Moduł jest super zestawem modułu npm fs, więc możesz korzystać ze wszystkich funkcji, fstakże po dodaniu tego modułu.
var dir = 'path/to/dir';
try {
fs.mkdirSync(dir);
} catch(e) {
if (e.code != 'EEXIST') throw e;
}
fs.exists()jest przestarzała, ale fs.existsSync()nie jest. Czy możesz dodać link do zasobu informującego, że fs.existsSync()jest amortyzowany?
Apr 2018: nodejs.org/api/fs.html#fs_fs_existssync_path
var filessystem = require('fs');
var dir = './path/subpath/';
if (!filessystem.existsSync(dir)){
filessystem.mkdirSync(dir);
}else
{
console.log("Directory already exist");
}
To może ci pomóc :)
ENOENT: brak takiego pliku lub katalogu
Rozwiązanie
const fs = require('fs') // in javascript
import * as fs from "fs" // in typescript
import fs from "fs" // in typescript
// it will create the directory if it does not exist.
!fs.existsSync(`./assets/`) && fs.mkdirSync(`./assets/`, { recursive: true })
Chciałbym dodać refaktor Typescript Promise do odpowiedzi josh3736 .
Robi to samo i ma te same przypadki brzegowe, po prostu używa Obietnic, maszynopisów maszynopisowych i działa z „use strict”.
// https://en.wikipedia.org/wiki/File_system_permissions#Numeric_notation
const allRWEPermissions = parseInt("0777", 8);
function ensureFilePathExists(path: string, mask: number = allRWEPermissions): Promise<void> {
return new Promise<void>(
function(resolve: (value?: void | PromiseLike<void>) => void,
reject: (reason?: any) => void): void{
mkdir(path, mask, function(err: NodeJS.ErrnoException): void {
if (err) {
if (err.code === "EEXIST") {
resolve(null); // ignore the error if the folder already exists
} else {
reject(err); // something else went wrong
}
} else {
resolve(null); // successfully created folder
}
});
});
}
W przypadku węzła 10 + ES6:
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;
}
}
})();
Możesz użyć węzła File System komendy fs.stat, aby sprawdzić, czy katalog istnieje, i fs.mkdir, aby utworzyć katalog z wywołaniem zwrotnym, lub fs.mkdirSync, aby utworzyć katalog bez wywołania zwrotnego, jak w tym przykładzie:
//first require fs
const 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);
}
});
};
Oto mała funkcja rekurencyjnego tworzenia katalogów:
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
}, '')
}
Za pomocą asynchronizacji / oczekiwania:
const mkdirP = async (directory) => {
try {
return await fs.mkdirAsync(directory);
} catch (error) {
if (error.code != 'EEXIST') {
throw e;
}
}
};
Musisz obiecać fs:
import nodeFs from 'fs';
import bluebird from 'bluebird';
const fs = bluebird.promisifyAll(nodeFs);