11# mkdirp
22
3- Like ` mkdir -p ` , but in node .js!
3+ Like ` mkdir -p ` , but in Node .js!
44
5- [ ![ build status] ( https://secure.travis-ci.org/substack/node-mkdirp.png )] ( http://travis-ci.org/substack/node-mkdirp )
5+ Now with a modern API and no\* bugs!
6+
7+ <small >\* may contain some bugs</small >
68
79# example
810
911## pow.js
1012
1113``` js
12- var mkdirp = require (' mkdirp' );
13-
14- mkdirp (' /tmp/foo/bar/baz' , function (err ) {
15- if (err) console .error (err)
16- else console .log (' pow!' )
17- });
14+ const mkdirp = require (' mkdirp' )
15+
16+ // return value is a Promise resolving to the first directory created
17+ mkdirp (' /tmp/foo/bar/baz' ).then (made =>
18+ console .log (` made directories, starting with ${ made} ` ))
1819```
1920
20- Output
21+ Output (where ` /tmp/foo ` already exists)
2122
2223```
23- pow!
24+ made directories, starting with /tmp/foo/bar
25+ ```
26+
27+ Or, if you don't have time to wait around for promises:
28+
29+ ``` js
30+ const mkdirp = require (' mkdirp' )
31+
32+ // return value is the first directory created
33+ const made = mkdirp .sync (' /tmp/foo/bar/baz' )
34+ console .log (` made directories, starting with ${ made} ` )
2435```
2536
2637And now /tmp/foo/bar/baz exists, huzzah!
2738
2839# methods
2940
3041``` js
31- var mkdirp = require (' mkdirp' );
42+ const mkdirp = require (' mkdirp' )
3243```
3344
34- ## mkdirp(dir, opts, cb)
45+ ## mkdirp(dir, [ opts] ) -> Promise<String | undefined>
3546
3647Create a new directory and any necessary subdirectories at ` dir ` with octal
37- permission string ` opts.mode ` . If ` opts ` is a non-object , it will be treated as
38- the ` opts.mode ` .
48+ permission string ` opts.mode ` . If ` opts ` is a string or number , it will be
49+ treated as the ` opts.mode ` .
3950
40- If ` opts.mode ` isn't specified, it defaults to ` 0777 & (~process.umask()) ` .
51+ If ` opts.mode ` isn't specified, it defaults to `0o777 &
52+ (~ process.umask())`.
4153
42- ` cb(err, made) ` fires with the error or the first directory ` made `
43- that had to be created, if any.
54+ Promise resolves to first directory ` made ` that had to be created, or
55+ ` undefined ` if everything already exists. Promise rejects if any errors
56+ are encountered. Note that, in the case of promise rejection, some
57+ directories _ may_ have been created, as recursive directory creation is not
58+ an atomic operation.
4459
4560You can optionally pass in an alternate ` fs ` implementation by passing in
46- ` opts.fs ` . Your implementation should have ` opts.fs.mkdir(path, mode , cb) ` and
47- ` opts.fs.stat(path, cb) ` .
61+ ` opts.fs ` . Your implementation should have ` opts.fs.mkdir(path, opts , cb) `
62+ and ` opts.fs.stat(path, cb) ` .
4863
49- ## mkdirp.sync(dir, opts)
64+ You can also override just one or the other of ` mkdir ` and ` stat ` by
65+ passing in ` opts.stat ` or ` opts.mkdir ` , or providing an ` fs ` option that
66+ only overrides one of these.
5067
51- Synchronously create a new directory and any necessary subdirectories at ` dir `
52- with octal permission string ` opts.mode ` . If ` opts ` is a non-object, it will be
53- treated as the ` opts.mode ` .
68+ ## mkdirp.sync(dir, opts) -> String|null
5469
55- If ` opts.mode ` isn't specified, it defaults to ` 0777 & (~process.umask()) ` .
70+ Synchronously create a new directory and any necessary subdirectories at
71+ ` dir ` with octal permission string ` opts.mode ` . If ` opts ` is a string or
72+ number, it will be treated as the ` opts.mode ` .
5673
57- Returns the first directory that had to be created, if any.
74+ If ` opts.mode ` isn't specified, it defaults to `0o777 &
75+ (~ process.umask())`.
76+
77+ Returns the first directory that had to be created, or undefined if
78+ everything already exists.
5879
5980You can optionally pass in an alternate ` fs ` implementation by passing in
60- ` opts.fs ` . Your implementation should have ` opts.fs.mkdirSync(path, mode) ` and
61- ` opts.fs.statSync(path) ` .
81+ ` opts.fs ` . Your implementation should have ` opts.fs.mkdirSync(path, mode) `
82+ and ` opts.fs.statSync(path) ` .
83+
84+ You can also override just one or the other of ` mkdirSync ` and ` statSync `
85+ by passing in ` opts.statSync ` or ` opts.mkdirSync ` , or providing an ` fs `
86+ option that only overrides one of these.
6287
63- # usage
88+ ## mkdirp.manual, mkdirp.manualSync
89+
90+ Use the manual implementation (not the native one). This is the default
91+ when the native implementation is not available or the stat/mkdir
92+ implementation is overridden.
93+
94+ ## mkdirp.native, mkdirp.nativeSync
95+
96+ Use the native implementation (not the manual one). This is the default
97+ when the native implementation is available and stat/mkdir are not
98+ overridden.
99+
100+ # implementation
101+
102+ On Node.js v10.12.0 and above, use the native `fs.mkdir(p,
103+ {recursive: true })` option, unless ` fs.mkdir` / ` fs.mkdirSync` has been
104+ overridden by an option.
105+
106+ ## native implementation
107+
108+ - If the path is a root directory, then pass it to the underlying
109+ implementation and return the result/error. (In this case, it'll either
110+ succeed or fail, but we aren't actually creating any dirs.)
111+ - Walk up the path statting each directory, to find the first path that
112+ will be created, ` made ` .
113+ - Call ` fs.mkdir(path, { recursive: true }) ` (or ` fs.mkdirSync ` )
114+ - If error, raise it to the caller.
115+ - Return ` made ` .
116+
117+ ## manual implementation
118+
119+ - Call underlying ` fs.mkdir ` implementation, with ` recursive: false `
120+ - If error:
121+ - If path is a root directory, raise to the caller and do not handle it
122+ - If ENOENT, mkdirp parent dir, store result as ` made `
123+ - stat(path)
124+ - If error, raise original ` mkdir ` error
125+ - If directory, return ` made `
126+ - Else, raise original ` mkdir ` error
127+ - else
128+ - return ` undefined ` if a root dir, or ` made ` if set, or ` path `
129+
130+ ## windows vs unix caveat
131+
132+ On Windows file systems, attempts to create a root directory (ie, a drive
133+ letter or root UNC path) will fail. If the root directory exists, then it
134+ will fail with ` EPERM ` . If the root directory does not exist, then it will
135+ fail with ` ENOENT ` .
136+
137+ On posix file systems, attempts to create a root directory (in recursive
138+ mode) will succeed silently, as it is treated like just another directory
139+ that already exists. (In non-recursive mode, of course, it fails with
140+ ` EEXIST ` .)
141+
142+ In order to preserve this system-specific behavior (and because it's not as
143+ if we can create the parent of a root directory anyway), attempts to create
144+ a root directory are passed directly to the ` fs ` implementation, and any
145+ errors encountered are not handled.
146+
147+ ## native error caveat
148+
149+ The native implementation (as of at least Node.js v13.4.0) does not provide
150+ appropriate errors in some cases (see
151+ [ nodejs/node #31481 ] ( https://github.com/nodejs/node/issues/31481 ) and
152+ [ nodejs/node #28015 ] ( https://github.com/nodejs/node/issues/28015 ) ).
153+
154+ In order to work around this issue, the native implementation will fall
155+ back to the manual implementation if an ` ENOENT ` error is encountered.
156+
157+ # choosing a recursive mkdir implementation
158+
159+ There are a few to choose from! Use the one that suits your needs best : D
160+
161+ ## use ` fs.mkdir(path, {recursive: true}, cb) ` if:
162+
163+ - You wish to optimize performance even at the expense of other factors.
164+ - You don't need to know the first dir created.
165+ - You are ok with getting ` ENOENT ` as the error when some other problem is
166+ the actual cause.
167+ - You can limit your platforms to Node.js v10.12 and above.
168+ - You're ok with using callbacks instead of promises.
169+ - You don't need/want a CLI.
170+ - You don't need to override the ` fs ` methods in use.
171+
172+ ## use this module (mkdirp 1.x) if:
173+
174+ - You need to know the first directory that was created.
175+ - You wish to use the native implementation if available, but fall back
176+ when it's not.
177+ - You prefer promise-returning APIs to callback-taking APIs.
178+ - You want more useful error messages than the native recursive mkdir
179+ provides (at least as of Node.js v13.4), and are ok with re-trying on
180+ ` ENOENT ` to achieve this.
181+ - You need (or at least, are ok with) a CLI.
182+ - You need to override the ` fs ` methods in use.
183+
184+ ## use [ `make-dir] ( http://npm.im/make-dir ) if:
185+
186+ - You do not need to know the first dir created (and wish to save a few
187+ ` stat ` calls when using the native implementation for this reason).
188+ - You wish to use the native implementation if available, but fall back
189+ when it's not.
190+ - You prefer promise-returning APIs to callback-taking APIs.
191+ - You are ok with occasionally getting ` ENOENT ` errors for failures that
192+ are actually related to something other than a missing file system entry.
193+ - You don't need/want a CLI.
194+ - You need to override the ` fs ` methods in use.
195+
196+ ## use mkdirp 0.x if:
197+
198+ - You need to know the first directory that was created.
199+ - You need (or at least, are ok with) a CLI.
200+ - You need to override the ` fs ` methods in use.
201+ - You're ok with using callbacks instead of promises.
202+ - You are not running on Windows, where the root-level ENOENT errors can
203+ lead to infinite regress.
204+ - You think vinyl just sounds warmer and richer for some weird reason.
205+ - You are supporting truly ancient Node.js versions, before even the advent
206+ of a ` Promise ` language primitive. (Please don't. You deserve better.)
207+
208+ # cli
64209
65210This package also ships with a ` mkdirp ` command.
66211
67212```
213+ $ mkdirp -h
214+
68215usage: mkdirp [DIR1,DIR2..] {OPTIONS}
69216
70- Create each supplied directory including any necessary parent directories that
71- don't yet exist.
72-
217+ Create each supplied directory including any necessary parent directories
218+ that don't yet exist.
219+
73220 If the directory already exists, do nothing.
74221
75222OPTIONS are:
76223
77- -m, --mode If a directory needs to be created, set the mode as an octal
78- permission string.
224+ -m<mode> If a directory needs to be created, set the mode as an octal
225+ --mode=<mode> permission string.
226+
227+ -v --version Print the mkdirp version number
79228
229+ -h --help Print this helpful banner
230+
231+ -p --print Print the first directories created for each path provided
232+
233+ --manual Use manual implementation, even if native is available
80234```
81235
82236# install
@@ -87,13 +241,25 @@ With [npm](http://npmjs.org) do:
87241npm install mkdirp
88242```
89243
90- to get the library, or
244+ to get the library locally , or
91245
92246```
93247npm install -g mkdirp
94248```
95249
96- to get the command.
250+ to get the command everywhere, or
251+
252+ ```
253+ npx mkdirp ...
254+ ```
255+
256+ to run the command without installing it globally.
257+
258+ # platform support
259+
260+ This module works on node v8, but only v10 and above are officially
261+ supported, as Node v8 reached its LTS end of life 2020-01-01, which is in
262+ the past, as of this writing.
97263
98264# license
99265
0 commit comments