Bagaimana cara menulis file jika folder induk tidak ada?

94

Saya perlu menulis file ke jalur berikut:

fs.writeFile('/folder1/folder2/file.txt', 'content', function () {…});

Tapi '/folder1/folder2'jalan mungkin tidak ada. Jadi saya mendapatkan kesalahan berikut:

message = ENOENT, buka /folder1/folder2/file.txt

Bagaimana saya bisa menulis konten ke jalur itu?

Erik
sumber
2
fs.promises.mkdir(path.dirname('/folder1/folder2/file.txt'), {recursive: true}).then(x => fs.promises.writeFile('/folder1/folder2/file.txt', 'content'))
Offenso

Jawaban:

128

Gunakan mkdirp yang dikombinasikan dengan yang path.dirnamepertama.

var mkdirp = require('mkdirp');
var fs = require('fs');
var getDirName = require('path').dirname;

function writeFile(path, contents, cb) {
  mkdirp(getDirName(path), function (err) {
    if (err) return cb(err);

    fs.writeFile(path, contents, cb);
  });
}

Jika seluruh jalur sudah ada, mkdirpadalah noop. Jika tidak, itu membuat semua direktori yang hilang untuk Anda.

Modul ini melakukan apa yang Anda inginkan: https://npmjs.org/package/writefile . Mengerti saat mencari di Google untuk "writefile mkdirp". Modul ini mengembalikan sebuah janji alih-alih menerima panggilan balik, jadi pastikan untuk membaca beberapa pengantar janji terlebih dahulu. Ini mungkin benar-benar memperumit masalah Anda.

Fungsi yang saya berikan berfungsi dalam hal apa pun.

Myrne Stol
sumber
Jadi jika kita ingin menunggu sampai selesai kita harus memasukkan semuanya setelah itu ke dalam panggilan balik? Apakah ada cara lain?
pete
@pete jika Anda menggunakan babel, Anda dapat menggunakan async / menunggu seperti ini: gist.github.com/lucasreppewelander/…
Lucas Reppe Welander
11
Gunakan rekursif:fs.promises.mkdir(path.dirname(file), {recursive: true}).then(x => fs.promises.writeFile(file, data))
Offenso
27

Saya menemukan bahwa cara termudah untuk melakukannya adalah dengan menggunakan metode outputFile () dari modul fs-extra .

Hampir sama dengan writeFile (yaitu menimpa), kecuali jika direktori induk tidak ada, itu dibuat. opsinya adalah apa yang akan Anda teruskan ke fs.writeFile ().

Contoh:

var fs = require('fs-extra');
var file = '/tmp/this/path/does/not/exist/file.txt'

fs.outputFile(file, 'hello!', function (err) {
    console.log(err); // => null

    fs.readFile(file, 'utf8', function (err, data) {
        console.log(data); // => hello!
    });
});

Ini juga memiliki dukungan menjanjikan di luar kotak hari ini !.

tkarls
sumber
21

Edit

Versi NodeJS 10.12.0telah menambahkan dukungan asli untuk keduanya mkdirdan mkdirSyncuntuk membuat direktur induk secara rekursif dengan recursive: trueopsi sebagai berikut:

fs.mkdirSync(targetDir, { recursive: true });

Dan jika Anda mau fs Promises API, Anda bisa menulis

fs.promises.mkdir(targetDir, { recursive: true });

Jawaban Asli

Buat direktori induk secara rekursif jika tidak ada! ( Nol ketergantungan )

const fs = require('fs');
const path = require('path');

function mkDirByPathSync(targetDir, { isRelativeToScript = false } = {}) {
  const sep = path.sep;
  const initDir = path.isAbsolute(targetDir) ? sep : '';
  const baseDir = isRelativeToScript ? __dirname : '.';

  return targetDir.split(sep).reduce((parentDir, childDir) => {
    const curDir = path.resolve(baseDir, parentDir, childDir);
    try {
      fs.mkdirSync(curDir);
    } catch (err) {
      if (err.code === 'EEXIST') { // curDir already exists!
        return curDir;
      }

      // To avoid `EISDIR` error on Mac and `EACCES`-->`ENOENT` and `EPERM` on Windows.
      if (err.code === 'ENOENT') { // Throw the original parentDir error on curDir `ENOENT` failure.
        throw new Error(`EACCES: permission denied, mkdir '${parentDir}'`);
      }

      const caughtErr = ['EACCES', 'EPERM', 'EISDIR'].indexOf(err.code) > -1;
      if (!caughtErr || caughtErr && curDir === path.resolve(targetDir)) {
        throw err; // Throw if it's just the last created dir.
      }
    }

    return curDir;
  }, initDir);
}

Pemakaian

// Default, make directories relative to current working directory.
mkDirByPathSync('path/to/dir');

// Make directories relative to the current script.
mkDirByPathSync('path/to/dir', {isRelativeToScript: true});

// Make directories with an absolute path.
mkDirByPathSync('/path/to/dir');

Demo

Cobalah!

Penjelasan

  • [PEMBARUAN] Solusi ini menangani kesalahan khusus platform seperti EISDIRuntuk Mac dan EPERMdan EACCESuntuk Windows.
  • Solusi ini menangani jalur relatif dan absolut .
  • Dalam kasus jalur relatif, direktori target akan dibuat (diselesaikan) di direktori kerja saat ini. Untuk mengatasinya relatif terhadap direktori skrip saat ini, teruskan {isRelativeToScript: true}.
  • Menggunakan path.sepdan path.resolve(), bukan hanya /penggabungan, untuk menghindari masalah lintas platform.
  • Menggunakan fs.mkdirSyncdan menangani kesalahan dengan try/catchjika dilempar untuk menangani kondisi balapan: proses lain mungkin menambahkan file antara panggilan ke fs.existsSync()dan fs.mkdirSync()dan menyebabkan pengecualian.
    • Cara lain untuk mencapainya bisa dengan memeriksa apakah sebuah file ada kemudian membuatnya, yaitu if (!fs.existsSync(curDir) fs.mkdirSync(curDir);. Tapi ini adalah anti-pola yang membuat kode rentan terhadap kondisi balapan.
  • Membutuhkan Node v6 dan yang lebih baru untuk mendukung perusakan. (Jika Anda memiliki masalah dalam mengimplementasikan solusi ini dengan versi Node lama, tinggalkan saya komentar)
Mouneer
sumber
19

Mungkin yang paling sederhana, Anda bisa menggunakan modul fs-path npm.

Kode Anda akan terlihat seperti ini:

var fsPath = require('fs-path');

fsPath.writeFile('/folder1/folder2/file.txt', 'content', function(err){
  if(err) {
    throw err;
  } else {
    console.log('wrote a file like DaVinci drew machines');
  }
});
kevincoleman
sumber
3

Kamu bisa memakai

fs.stat('/folder1/folder2', function(err, stats){ ... });

statsadalah fs.Statsjenis objek, Anda dapat memeriksanya stats.isDirectory(). Tergantung pada pemeriksaan errdan statsAnda dapat melakukan sesuatu, fs.mkdir( ... )atau membuat kesalahan.

Referensi

Pembaruan: Memperbaiki koma dalam kode.

MikeD
sumber
Jadi saya tidak bisa menulis file dengan menggunakan perintah sibgle di nodejs?
Erik
3

Dengan node-fs-extra, Anda dapat melakukannya dengan mudah.

Pasang itu

npm install --save fs-extra

Kemudian gunakan metode outputFile sebagai ganti writeFileSync

const fs = require('fs-extra');

fs.outputFile('tmp/test.txt', 'Hey there!', err => {
  if(err) {
    console.log(err);
  } else {
    console.log('The file was saved!');
  }
})
Muhammad Numan
sumber
2

Inilah fungsi khusus saya untuk membuat direktori secara rekursif (tanpa ketergantungan eksternal):

var fs = require('fs');
var path = require('path');

var myMkdirSync = function(dir){
    if (fs.existsSync(dir)){
        return
    }

    try{
        fs.mkdirSync(dir)
    }catch(err){
        if(err.code == 'ENOENT'){
            myMkdirSync(path.dirname(dir)) //create parent dir
            myMkdirSync(dir) //create dir
        }
    }
}

myMkdirSync(path.dirname(filePath));
var file = fs.createWriteStream(filePath);
math_lab3.ca
sumber
2

Ini adalah fungsi saya yang bekerja di Node 10.12.0. Semoga ini bisa membantu.

const fs = require('fs');
function(dir,filename,content){
        fs.promises.mkdir(dir, { recursive: true }).catch(error => { console.error('caught exception : ', error.message); });
        fs.writeFile(dir+filename, content, function (err) {
            if (err) throw err;
            console.info('file saved!');
        });
    }
Kailash
sumber
0
let name = "./new_folder/" + file_name + ".png";
await driver.takeScreenshot().then(
  function(image, err) {
    require('mkdirp')(require('path').dirname(name), (err) => {
      require('fs').writeFile(name, image, 'base64', function(err) {
        console.log(err);
      });
    });
  }
);
Luat Do
sumber
Jawaban hanya kode dianggap berkualitas rendah: pastikan untuk memberikan penjelasan tentang fungsi kode Anda dan bagaimana cara menyelesaikan masalah. Ini akan membantu penanya dan pembaca yang akan datang jika Anda dapat menambahkan lebih banyak informasi dalam posting Anda. Lihat Menjelaskan sepenuhnya jawaban berbasis kode
Calos
-1

Inilah bagian dari jawaban Myrne Stol yang dipecah sebagai jawaban terpisah:

Modul ini melakukan apa yang Anda inginkan: https://npmjs.org/package/writefile . Mengerti saat mencari di Google untuk "writefile mkdirp". Modul ini mengembalikan sebuah janji alih-alih menerima panggilan balik, jadi pastikan untuk membaca beberapa pengantar janji terlebih dahulu. Ini mungkin benar-benar memperumit masalah Anda.

David Braun
sumber