วิธีการสร้างเส้นทางแบบเต็มด้วยโหนด fs.mkdirSync?


159

ฉันกำลังพยายามสร้างเส้นทางแบบเต็มหากไม่มีอยู่จริง

รหัสมีลักษณะดังนี้:

var fs = require('fs');
if (!fs.existsSync(newDest)) fs.mkdirSync(newDest); 

รหัสนี้ใช้งานได้ดีตราบใดที่มีเพียงไดเรกทอรีย่อยเดียว (newDest เช่น 'dir1') อย่างไรก็ตามเมื่อมีเส้นทางไดเรกทอรีเช่น ('dir1 / dir2') มันล้มเหลวด้วย ข้อผิดพลาด: ENOENT ไม่มีไฟล์หรือไดเรกทอรีดังกล่าว

ฉันต้องการสร้างเส้นทางแบบเต็มโดยใช้โค้ดไม่กี่บรรทัดเท่าที่จำเป็น

ฉันอ่านมีตัวเลือกซ้ำบน fs และลองแบบนี้

var fs = require('fs');
if (!fs.existsSync(newDest)) fs.mkdirSync(newDest,'0777', true);

ฉันรู้สึกว่าควรเป็นเรื่องง่ายที่จะสร้างไดเรกทอรีที่ไม่มีอยู่ซ้ำ ๆ ฉันทำบางสิ่งขาดหายไปหรือต้องแยกวิเคราะห์เส้นทางและตรวจสอบแต่ละไดเรกทอรีแล้วสร้างมันถ้ามันยังไม่มีอยู่

ฉันค่อนข้างใหม่กับโหนด บางทีฉันกำลังใช้ FS เวอร์ชันเก่าอยู่ใช่ไหม


1
github.com/substack/node-mkdirpและทุกประเภทของการแก้ปัญหาอื่น ๆ ในการค้นหาของ Google นี้
jfriend00

4
@AndyRay คำถาม StackOverflow ตอนนี้เป็นผลลัพธ์อันดับต้น ๆ ใน google สำหรับคำถามนี้ซึ่งเป็นเรื่องตลกเพราะนั่นหมายความว่ามันจะเกิดขึ้นซ้ำอีกครั้ง ...
Matt Parkins

1
นั่นเป็นปัญหาในโหนดที่เก่ากว่าการอัปเดตเป็น Node 12+ แก้ปัญหาได้
MrJomp

คำตอบ:


48

ทางเลือกหนึ่งคือการใช้โมดูล shelljs

npm ติดตั้ง shelljs

var shell = require('shelljs');
shell.mkdir('-p', fullPath);

จากหน้านั้น:

ตัวเลือกที่มี:

p: เส้นทางแบบเต็ม (จะสร้าง dirs ระดับกลางหากจำเป็น)

ดังที่คนอื่น ๆ สังเกตเห็นมีโมดูลอื่น ๆ ที่มุ่งเน้นมากขึ้น แต่นอกเหนือจาก mkdirp มันมีการทำงานของเชลล์ที่มีประโยชน์มากมาย (เช่น grep และอื่น ๆ ... ) และมันทำงานบน windows และ * nix


2
ขอบคุณ! ฉันลงเอยด้วยการใช้ exec (ฉันใช้สิ่งนี้อยู่แล้ว) และมันใช้งานได้อย่างมีเสน่ห์ var exec = ต้องการ ('child_process'). exec; คำสั่ง var = "mkdir -p '" + newDest + "'"; ตัวเลือก var = {}; var after = function (ข้อผิดพลาด, stdout, stderr) {console.log ('ข้อผิดพลาด', ข้อผิดพลาด); console.log ('stdout', stdout); console.log ('stderr', stderr); } exec (คำสั่งตัวเลือกหลังจาก);
David Silva Smith

24
ตัวเลือกนี้อาจแตกบนแพลตฟอร์ม node.js ที่ไม่มีอินสแตนซ์บรรทัดคำสั่ง mkdir (เช่นโฮสต์ที่ไม่ใช่ Linux-y) ดังนั้นจึงไม่สามารถพกพาได้
cshotton

1
@cshotton - คุณหมายถึงความคิดเห็นหรือคำตอบ? shelljs ทำงานได้แม้ใน Windows exec mkdir -p (ความคิดเห็น) แน่นอนไม่ได้
bryanmac

คุณสามารถใช้ฟังก์ชั่นเจ๋ง ๆ นี้กับ Promise หรือโทรกลับตามที่คุณต้องการ
ИльяЗеленько

1
นี่ไม่ใช่วิธีแก้ปัญหานี่เป็นทางเลือกสำหรับโซลูชัน บริบท: pics.onsizzle.com/…
Nika Kasradze

413

แก้ไข

รุ่น NodeJS 10.12.0ได้เพิ่มการสนับสนุนแบบเนทีฟสำหรับทั้งคู่mkdirและmkdirSyncเพื่อสร้างไดเร็กทอรีแบบเรียกซ้ำโดยมีrecursive: trueอ็อพชันดังต่อไปนี้:

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

และถ้าคุณต้องการfs Promises APIคุณสามารถเขียน

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

คำตอบเดิม

สร้างไดเรกทอรีซ้ำหากไม่มีอยู่! (การพึ่งพาศูนย์ )

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);
}

การใช้

// 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');

การสาธิต

ลองมัน!

คำอธิบาย

  • [อัพเดท]โซลูชั่นนี้จัดการข้อผิดพลาดเฉพาะแพลตฟอร์มเช่นEISDIRสำหรับ Mac EPERMและEACCESสำหรับ Windows ขอบคุณที่รายงานความคิดเห็นทั้งหมดโดย @PediT., @JohnQ, @ deed02392, @robyoder และ @Almenon
  • โซลูชันนี้จัดการทั้งเส้นทางแบบสัมพันธ์และเส้นทางแบบสัมบูรณ์ ขอบคุณ @john แสดงความคิดเห็น
  • ในกรณีของเส้นทางสัมพัทธ์ไดเรกทอรีเป้าหมายจะถูกสร้างขึ้น (แก้ไข) ในไดเรกทอรีการทำงานปัจจุบัน การแก้ไขปัญหาที่เกี่ยวข้องกับ dir {isRelativeToScript: true}สคริปต์ปัจจุบันผ่าน
  • การใช้path.sepและpath.resolve()ไม่เพียงแค่การ/ต่อข้อมูลเพื่อหลีกเลี่ยงปัญหาข้ามแพลตฟอร์ม
  • การใช้fs.mkdirSyncและการจัดการข้อผิดพลาดด้วยtry/catchถ้าถูกโยนเพื่อจัดการกับสภาพการแข่งขัน: กระบวนการอื่นอาจเพิ่มไฟล์ระหว่างการเรียกfs.existsSync()และfs.mkdirSync()และทำให้เกิดข้อยกเว้น
    • อีกวิธีหนึ่งที่จะทำให้บรรลุผลนั้นสามารถตรวจสอบได้ว่ามีไฟล์อยู่หรือif (!fs.existsSync(curDir) fs.mkdirSync(curDir);ไม่ แต่นี่เป็นรูปแบบการต่อต้านที่ทำให้รหัสเสี่ยงต่อการแข่งขัน ขอบคุณ @GershomMaes แสดงความคิดเห็นเกี่ยวกับการตรวจสอบการมีอยู่ของไดเรกทอรี
  • ต้องการNode v6และใหม่กว่าเพื่อรองรับการทำลายล้าง (หากคุณมีปัญหาในการใช้โซลูชันนี้กับโหนดรุ่นเก่าเพียงแค่แสดงความคิดเห็น)

7
โหวตขึ้นเพื่อความสะดวกในการตอบกลับแบบเรียกซ้ำไม่ต้องใช้ห้องสมุดหรือแนวทางเพิ่มเติม!
MikingTheViking

1
ไม่มีคำสั่งที่ต้องการ: const fs = require ('fs'); const path = require ('path');
Christopher Bull

1
@ChristopherBull โดยเจตนาไม่ได้เพิ่มเพียงเพื่อมุ่งเน้นไปที่ตรรกะ แต่ยังไงก็ตามฉันเพิ่มพวกเขา ขอบคุณ;)
Mouneer

1
รหัสโซลิด 12 บรรทัด, การอ้างอิงเป็นศูนย์, ฉันจะรับมันทุกครั้ง
moodboom

1
@ Mouneer บน Mac OS X 10.12.6 ข้อผิดพลาดเกิดขึ้นเมื่อพยายามสร้าง "/" หลังจากผ่านเส้นทางสัมบูรณ์คือ "EISDIR" (ข้อผิดพลาด: EISDIR: การดำเนินการที่ผิดกฎหมายในไดเรกทอรี mkdir '/') ฉันคิดว่าอาจตรวจสอบการมีอยู่ของ dir ยังคงเป็นวิธีข้ามแพลตฟอร์มที่ดีที่สุด (ยอมรับว่ามันจะช้ากว่า)
John Q

78

คำตอบที่มีประสิทธิภาพมากขึ้นคือการใช้การใช้mkdirp

var mkdirp = require('mkdirp');

mkdirp('/path/to/dir', function (err) {
    if (err) console.error(err)
    else console.log('dir created')
});

จากนั้นดำเนินการเขียนไฟล์ลงในพา ธ เต็มด้วย:

fs.writeFile ('/path/to/dir/file.dat'....

ต้องการคำตอบนี้เพราะคุณกำลังนำเข้าสิ่งที่คุณต้องการไม่ใช่ห้องสมุดทั้งหมด
Juan Mendes

1
ขอแสดงความยินดีกับตราประชานิยม ;-)
janos

1
ขอบคุณ มันเป็นวิธีที่ดีที่สุด
Stepan Rafael


48

fs-extra เพิ่มวิธีระบบไฟล์ที่ไม่รวมอยู่ในโมดูล fs ดั้งเดิม เป็นแบบเลื่อนแทน fs

ติดตั้ง fs-extra

$ npm install --save fs-extra

const fs = require("fs-extra");
// Make sure the output directory is there.
fs.ensureDirSync(newDest);

มีตัวเลือกการซิงค์และ async

https://github.com/jprichardson/node-fs-extra/blob/master/docs/ensureDir.md


5
นี่คือคำตอบที่ดีที่สุด! พวกเราส่วนใหญ่มี fs-พิเศษในแอพ
pagep

มันจะดีมากถ้ามันมีความเป็นไปได้ที่จะใช้memfsสำหรับการทดสอบหน่วย ไม่ :-( github.com/jprichardson/node-fs-extra/issues/274
schnatterer

31

ใช้ลดเราสามารถตรวจสอบว่าแต่ละเส้นทางที่มีอยู่และสร้างถ้าจำเป็นด้วยวิธีนี้ฉันคิดว่ามันง่ายต่อการปฏิบัติตาม แก้ไขขอบคุณ @Arvin เราควรใช้ path.sep เพื่อรับตัวแยกส่วนเส้นทางเฉพาะแพลตฟอร์มที่เหมาะสม

const path = require('path');

// Path separators could change depending on the platform
const pathToCreate = 'path/to/dir'; 
pathToCreate
 .split(path.sep)
 .reduce((prevPath, folder) => {
   const currentPath = path.join(prevPath, folder, path.sep);
   if (!fs.existsSync(currentPath)){
     fs.mkdirSync(currentPath);
   }
   return currentPath;
 }, '');

4
เมื่อให้คำตอบดีกว่าให้คำอธิบายว่าทำไมคำตอบของคุณจึงเป็นคำตอบ
Stephen Rauch

ขออภัยคุณคิดถูกฉันคิดว่าวิธีนี้จะสะอาดและง่ายต่อการติดตาม
josebui

4
@josebui ฉันคิดว่าเป็นการดีกว่าถ้าใช้ "path.sep" แทนที่จะใช้เครื่องหมายทับ (/) เพื่อหลีกเลี่ยงปัญหาด้านสภาพแวดล้อม
Arvin

ทางออกที่ดีเพราะไม่ต้องการโหนด> = 10 เช่นคำตอบอื่น ๆ
Karim

29

คุณลักษณะนี้ถูกเพิ่มเข้ากับ node.js ในเวอร์ชัน 10.12.0 ดังนั้นจึงเป็นเรื่องง่ายเหมือนการส่งตัวเลือก{recursive: true}เป็นอาร์กิวเมนต์ที่สองไปยังการfs.mkdir()โทร ดูตัวอย่างในเอกสารอย่างเป็นทางการ

ไม่จำเป็นต้องใช้โมดูลภายนอกหรือการใช้งานของคุณเอง


1
ฉันพบคำขอดึงที่เกี่ยวข้องgithub.com/nodejs/node/pull/23313
nurettin

1
มันจะโยนข้อผิดพลาดเมื่อมีไดเรกทอรีและหยุด ใช้บล็อก catch ลองสามารถทำให้มันสร้างโฟลเดอร์อื่น ๆ ที่ไม่มีอยู่
Choco Li

1
นี่ควรเป็นคำตอบที่ยอมรับได้ มันจะไม่โยนหากไดเรกทอรีมีอยู่แล้วและสามารถใช้กับ async / await ผ่าน fs.promises.mkdir
Apodaca รวย

7

ฉันรู้ว่านี่เป็นคำถามเก่า แต่ตอนนี้ nodejs v10.12.0 รองรับสิ่งนี้ด้วยrecursiveตัวเลือกที่ตั้งค่าเป็นจริง fs.mkdir

// Creates /tmp/a/apple, regardless of whether `/tmp` and /tmp/a exist.
fs.mkdir('/tmp/a/apple', { recursive: true }, (err) => {
  if (err) throw err;
});


2

ตัวอย่างสำหรับ Windows (ไม่มีการขึ้นต่อกันพิเศษและการจัดการข้อผิดพลาด)

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

let dir = "C:\\temp\\dir1\\dir2\\dir3";

function createDirRecursively(dir) {
    if (!fs.existsSync(dir)) {        
        createDirRecursively(path.join(dir, ".."));
        fs.mkdirSync(dir);
    }
}

createDirRecursively(dir); //creates dir1\dir2\dir3 in C:\temp

2

คุณสามารถตรวจสอบโฟลเดอร์ที่มีอยู่หรือไม่อยู่ในเส้นทางแบบวนซ้ำและสร้างโฟลเดอร์ตามที่คุณตรวจสอบว่าไม่มีอยู่หรือไม่ ( ไม่มีห้องสมุดภายนอก )

function checkAndCreateDestinationPath (fileDestination) {
    const dirPath = fileDestination.split('/');
    dirPath.forEach((element, index) => {
        if(!fs.existsSync(dirPath.slice(0, index + 1).join('/'))){
            fs.mkdirSync(dirPath.slice(0, index + 1).join('/')); 
        }
    });
}

2

คุณสามารถใช้ฟังก์ชั่นต่อไป

const recursiveUpload = (path: string) => {const path = path.split ("/")

const fullPath = paths.reduce((accumulator, current) => {
  fs.mkdirSync(accumulator)
  return `${accumulator}/${current}`
  })

  fs.mkdirSync(fullPath)

  return fullPath
}

ดังนั้นมันทำอะไร:

  1. สร้างpathsตัวแปรที่มันเก็บทุกเส้นทางด้วยตัวเองเป็นองค์ประกอบของอาร์เรย์
  2. เพิ่ม "/" ที่ส่วนท้ายของแต่ละองค์ประกอบในอาร์เรย์
  3. ทำให้วงจร:
    1. สร้างไดเรกทอรีจากการเชื่อมต่อขององค์ประกอบอาร์เรย์ซึ่งดัชนีมาจาก 0 ถึงการวนซ้ำปัจจุบัน โดยทั่วไปจะเป็นแบบเรียกซ้ำ

หวังว่าจะช่วย!

โดยวิธีการในโหนด v10.12.0 คุณสามารถใช้การสร้างเส้นทางแบบเรียกซ้ำโดยให้มันเป็นอาร์กิวเมนต์เพิ่มเติม

fs.mkdir('/tmp/a/apple', { recursive: true }, (err) => { if (err) throw err; });

https://nodejs.org/api/fs.html#fs_fs_mkdirsync_path_options


1

มีคำตอบมากเกินไป แต่นี่เป็นวิธีการแก้ปัญหาที่ไม่มีการเรียกซ้ำที่ทำงานได้โดยแยกเส้นทางแล้วสร้างจากซ้ายไปขวาสำรองอีกครั้ง

function mkdirRecursiveSync(path) {
    let paths = path.split(path.delimiter);
    let fullPath = '';
    paths.forEach((path) => {

        if (fullPath === '') {
            fullPath = path;
        } else {
            fullPath = fullPath + '/' + path;
        }

        if (!fs.existsSync(fullPath)) {
            fs.mkdirSync(fullPath);
        }
    });
};

สำหรับผู้ที่กังวลเกี่ยวกับความเข้ากันได้กับ windows และ Linux เพียงแค่แทนที่เครื่องหมายทับหน้าด้วย double backslash '\' ในเหตุการณ์ทั้งสองข้างต้น แต่ TBH เรากำลังพูดถึงโหนด fs ไม่ใช่บรรทัดคำสั่งของ windows และอดีตคือการให้อภัย Windows และเป็นโซลูชันข้ามแพลตฟอร์มที่สมบูรณ์ยิ่งขึ้น


ไฟล์บน windows ได้รับการจัดการด้วยแบ็กสแลชไม่ใช่ฟอร์เวิร์ดสแลช รหัสของคุณจะไม่ทำงานที่นั่น C: \ data \ test ...
DDD

แก้ไข แต่แนะนำให้คุณตรวจสอบความคิดเห็นของคุณ บนโหนดลองต่อไปนี้และดูว่าเกิดอะไรขึ้น var fs = require ('fs') fs.mkdirSync ('ทดสอบ') fs.mkdirSync ('ทดสอบ \\ test1') fs.mkdirSync ('ทดสอบ / test2')
Hamiora

ไม่ว่าคุณจะพูดอะไร .. คะแนนโหวตของฉันยังคงอยู่จนกว่าคุณจะเรียนรู้ที่จะเขียนโค้ดที่ดีขึ้น
DDD

ฮ่าฮ่า ตกลงฉันจะทำงานหนักมากในการเรียนรู้วิธีเขียนโค้ดที่ดีกว่า BTW คำตอบส่วนใหญ่ข้างต้นรวมถึง OP ใช้เครื่องหมายทับซ้าย แนะนำให้คุณหยุดหมุนรอบ
Hamiora

1
path.sepกำลังผ่านเป็น / หรือ \\ สำหรับฉัน path.delimiterคือ: หรือ;
Josh Anderson Slate

1
const fs = require('fs');

try {
    fs.mkdirSync(path, { recursive: true });
} catch (error) {
    // this make script keep running, even when folder already exist
    console.log(error);
}

0

วิธีแบบอะซิงโครนัสเพื่อสร้างไดเรกทอรีซ้ำ:

import fs from 'fs'

const mkdirRecursive = function(path, callback) {
  let controlledPaths = []
  let paths = path.split(
    '/' // Put each path in an array
  ).filter(
    p => p != '.' // Skip root path indicator (.)
  ).reduce((memo, item) => {
    // Previous item prepended to each item so we preserve realpaths
    const prevItem = memo.length > 0 ? memo.join('/').replace(/\.\//g, '')+'/' : ''
    controlledPaths.push('./'+prevItem+item)
    return [...memo, './'+prevItem+item]
  }, []).map(dir => {
    fs.mkdir(dir, err => {
      if (err && err.code != 'EEXIST') throw err
      // Delete created directory (or skipped) from controlledPath
      controlledPaths.splice(controlledPaths.indexOf(dir), 1)
      if (controlledPaths.length === 0) {
        return callback()
      }
    })
  })
}

// Usage
mkdirRecursive('./photos/recent', () => {
  console.log('Directories created succesfully!')
})

0

นี่เป็นเวอร์ชั่นบังคับmkdirpสำหรับ nodejs ของฉัน

function mkdirSyncP(location) {
    let normalizedPath = path.normalize(location);
    let parsedPathObj = path.parse(normalizedPath);
    let curDir = parsedPathObj.root;
    let folders = parsedPathObj.dir.split(path.sep);
    folders.push(parsedPathObj.base);
    for(let part of folders) {
        curDir = path.join(curDir, part);
        if (!fs.existsSync(curDir)) {
            fs.mkdirSync(curDir);
        }
    }
}

0

วิธีการเกี่ยวกับวิธีนี้:

if (!fs.existsSync(pathToFile)) {
            var dirName = "";
            var filePathSplit = pathToFile.split('/');
            for (var index = 0; index < filePathSplit.length; index++) {
                dirName += filePathSplit[index]+'/';
                if (!fs.existsSync(dirName))
                    fs.mkdirSync(dirName);
            }
        }

ใช้งานได้กับพา ธ ที่เกี่ยวข้อง


0

จากคำตอบการพึ่งพาศูนย์ของ mouneerนี่เป็นTypescriptตัวแปรเริ่มต้นที่เป็นมิตรมากกว่าเล็กน้อยในฐานะโมดูล:

import * as fs from 'fs';
import * as path from 'path';

/**
* Recursively creates directories until `targetDir` is valid.
* @param targetDir target directory path to be created recursively.
* @param isRelative is the provided `targetDir` a relative path?
*/
export function mkdirRecursiveSync(targetDir: string, isRelative = false) {
    const sep = path.sep;
    const initDir = path.isAbsolute(targetDir) ? sep : '';
    const baseDir = isRelative ? __dirname : '.';

    targetDir.split(sep).reduce((prevDirPath, dirToCreate) => {
        const curDirPathToCreate = path.resolve(baseDir, prevDirPath, dirToCreate);
        try {
            fs.mkdirSync(curDirPathToCreate);
        } catch (err) {
            if (err.code !== 'EEXIST') {
                throw err;
            }
            // caught EEXIST error if curDirPathToCreate already existed (not a problem for us).
        }

        return curDirPathToCreate; // becomes prevDirPath on next call to reduce
    }, initDir);
}

0

สะอาดเหมือนอย่างนี้ :)

function makedir(fullpath) {
  let destination_split = fullpath.replace('/', '\\').split('\\')
  let path_builder = destination_split[0]
  $.each(destination_split, function (i, path_segment) {
    if (i < 1) return true
    path_builder += '\\' + path_segment
    if (!fs.existsSync(path_builder)) {
      fs.mkdirSync(path_builder)
    }
  })
}

0

ฉันมีปัญหากับตัวเลือกการเรียกซ้ำของ fs.mkdir ดังนั้นฉันจึงสร้างฟังก์ชันที่ทำสิ่งต่อไปนี้:

  1. สร้างรายการของไดเรกทอรีทั้งหมดเริ่มต้นด้วย dir เป้าหมายสุดท้ายและทำงานถึงผู้ปกครองราก
  2. สร้างรายการใหม่ของไดเรกทอรีที่จำเป็นสำหรับฟังก์ชั่น mkdir ให้ทำงาน
  3. ทำให้แต่ละไดเรกทอรีที่ต้องการรวมถึงสุดท้าย

    function createDirectoryIfNotExistsRecursive(dirname) {
        return new Promise((resolve, reject) => {
           const fs = require('fs');
    
           var slash = '/';
    
           // backward slashes for windows
           if(require('os').platform() === 'win32') {
              slash = '\\';
           }
           // initialize directories with final directory
           var directories_backwards = [dirname];
           var minimize_dir = dirname;
           while (minimize_dir = minimize_dir.substring(0, minimize_dir.lastIndexOf(slash))) {
              directories_backwards.push(minimize_dir);
           }
    
           var directories_needed = [];
    
           //stop on first directory found
           for(const d in directories_backwards) {
              if(!(fs.existsSync(directories_backwards[d]))) {
                 directories_needed.push(directories_backwards[d]);
              } else {
                 break;
              }
           }
    
           //no directories missing
           if(!directories_needed.length) {
              return resolve();
           }
    
           // make all directories in ascending order
           var directories_forwards = directories_needed.reverse();
    
           for(const d in directories_forwards) {
              fs.mkdirSync(directories_forwards[d]);
           }
    
           return resolve();
        });
     }

-1

ผู้บริหารสามารถยุ่งบน windows มีวิธีแก้ปัญหา "nodie" เพิ่มเติม โดยพื้นฐานแล้วคุณมีการเรียกซ้ำเพื่อดูว่ามีไดเรกทอรีอยู่หรือไม่และดำดิ่งลงไปในเด็ก (ถ้ามีอยู่) หรือสร้างมันขึ้นมา นี่คือฟังก์ชั่นที่จะสร้างลูก ๆ และเรียกใช้ฟังก์ชันเมื่อเสร็จสิ้น:

fs = require('fs');
makedirs = function(path, func) {
 var pth = path.replace(/['\\]+/g, '/');
 var els = pth.split('/');
 var all = "";
 (function insertOne() {
   var el = els.splice(0, 1)[0];
   if (!fs.existsSync(all + el)) {
    fs.mkdirSync(all + el);
   }
   all += el + "/";
   if (els.length == 0) {
    func();
   } else {
     insertOne();
   }
   })();

}


-1

เวอร์ชั่นนี้ใช้งานได้ดีกับ Windows มากกว่าคำตอบอันดับต้น ๆ เพราะเข้าใจทั้งสองอย่าง/และpath.sepเพื่อให้เครื่องหมายทับ (forward slash) ทำงานบน Windows ได้อย่างที่ควรจะเป็น รองรับเส้นทางสัมบูรณ์และเส้นทางสัมพัทธ์ (สัมพันธ์กับprocess.cwd)

/**
 * Creates a folder and if necessary, parent folders also. Returns true
 * if any folders were created. Understands both '/' and path.sep as 
 * path separators. Doesn't try to create folders that already exist,
 * which could cause a permissions error. Gracefully handles the race 
 * condition if two processes are creating a folder. Throws on error.
 * @param targetDir Name of folder to create
 */
export function mkdirSyncRecursive(targetDir) {
  if (!fs.existsSync(targetDir)) {
    for (var i = targetDir.length-2; i >= 0; i--) {
      if (targetDir.charAt(i) == '/' || targetDir.charAt(i) == path.sep) {
        mkdirSyncRecursive(targetDir.slice(0, i));
        break;
      }
    }
    try {
      fs.mkdirSync(targetDir);
      return true;
    } catch (err) {
      if (err.code !== 'EEXIST') throw err;
    }
  }
  return false;
}

downvote สำหรับการสนับสนุน Windows ถูกต้องหรือไม่ ฉันพูดถึงมันใช้งานได้กับระบบปฏิบัติการอื่น ๆ ด้วยหรือไม่
Qwertie
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.