You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

README.md 7.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  1. # readdirp [![Build Status](https://secure.travis-ci.org/thlorenz/readdirp.svg)](http://travis-ci.org/thlorenz/readdirp)
  2. [![NPM](https://nodei.co/npm/readdirp.png?downloads=true&stars=true)](https://nodei.co/npm/readdirp/)
  3. Recursive version of [fs.readdir](http://nodejs.org/docs/latest/api/fs.html#fs_fs_readdir_path_callback). Exposes a **stream api**.
  4. ```javascript
  5. var readdirp = require('readdirp')
  6. , path = require('path')
  7. , es = require('event-stream');
  8. // print out all JavaScript files along with their size
  9. var stream = readdirp({ root: path.join(__dirname), fileFilter: '*.js' });
  10. stream
  11. .on('warn', function (err) {
  12. console.error('non-fatal error', err);
  13. // optionally call stream.destroy() here in order to abort and cause 'close' to be emitted
  14. })
  15. .on('error', function (err) { console.error('fatal error', err); })
  16. .pipe(es.mapSync(function (entry) {
  17. return { path: entry.path, size: entry.stat.size };
  18. }))
  19. .pipe(es.stringify())
  20. .pipe(process.stdout);
  21. ```
  22. Meant to be one of the recursive versions of [fs](http://nodejs.org/docs/latest/api/fs.html) functions, e.g., like [mkdirp](https://github.com/substack/node-mkdirp).
  23. **Table of Contents** *generated with [DocToc](http://doctoc.herokuapp.com/)*
  24. - [Installation](#installation)
  25. - [API](#api)
  26. - [entry stream](#entry-stream)
  27. - [options](#options)
  28. - [entry info](#entry-info)
  29. - [Filters](#filters)
  30. - [Callback API](#callback-api)
  31. - [allProcessed ](#allprocessed)
  32. - [fileProcessed](#fileprocessed)
  33. - [More Examples](#more-examples)
  34. - [stream api](#stream-api)
  35. - [stream api pipe](#stream-api-pipe)
  36. - [grep](#grep)
  37. - [using callback api](#using-callback-api)
  38. - [tests](#tests)
  39. # Installation
  40. npm install readdirp
  41. # API
  42. ***var entryStream = readdirp (options)***
  43. Reads given root recursively and returns a `stream` of [entry info](#entry-info)s.
  44. ## entry stream
  45. Behaves as follows:
  46. - `emit('data')` passes an [entry info](#entry-info) whenever one is found
  47. - `emit('warn')` passes a non-fatal `Error` that prevents a file/directory from being processed (i.e., if it is
  48. inaccessible to the user)
  49. - `emit('error')` passes a fatal `Error` which also ends the stream (i.e., when illegal options where passed)
  50. - `emit('end')` called when all entries were found and no more will be emitted (i.e., we are done)
  51. - `emit('close')` called when the stream is destroyed via `stream.destroy()` (which could be useful if you want to
  52. manually abort even on a non fatal error) - at that point the stream is no longer `readable` and no more entries,
  53. warning or errors are emitted
  54. - to learn more about streams, consult the very detailed
  55. [nodejs streams documentation](http://nodejs.org/api/stream.html) or the
  56. [stream-handbook](https://github.com/substack/stream-handbook)
  57. ## options
  58. - **root**: path in which to start reading and recursing into subdirectories
  59. - **fileFilter**: filter to include/exclude files found (see [Filters](#filters) for more)
  60. - **directoryFilter**: filter to include/exclude directories found and to recurse into (see [Filters](#filters) for more)
  61. - **depth**: depth at which to stop recursing even if more subdirectories are found
  62. - **entryType**: determines if data events on the stream should be emitted for `'files'`, `'directories'`, `'both'`, or `'all'`. Setting to `'all'` will also include entries for other types of file descriptors like character devices, unix sockets and named pipes. Defaults to `'files'`.
  63. - **lstat**: if `true`, readdirp uses `fs.lstat` instead of `fs.stat` in order to stat files and includes symlink entries in the stream along with files.
  64. ## entry info
  65. Has the following properties:
  66. - **parentDir** : directory in which entry was found (relative to given root)
  67. - **fullParentDir** : full path to parent directory
  68. - **name** : name of the file/directory
  69. - **path** : path to the file/directory (relative to given root)
  70. - **fullPath** : full path to the file/directory found
  71. - **stat** : built in [stat object](http://nodejs.org/docs/v0.4.9/api/fs.html#fs.Stats)
  72. - **Example**: (assuming root was `/User/dev/readdirp`)
  73. parentDir : 'test/bed/root_dir1',
  74. fullParentDir : '/User/dev/readdirp/test/bed/root_dir1',
  75. name : 'root_dir1_subdir1',
  76. path : 'test/bed/root_dir1/root_dir1_subdir1',
  77. fullPath : '/User/dev/readdirp/test/bed/root_dir1/root_dir1_subdir1',
  78. stat : [ ... ]
  79. ## Filters
  80. There are three different ways to specify filters for files and directories respectively.
  81. - **function**: a function that takes an entry info as a parameter and returns true to include or false to exclude the entry
  82. - **glob string**: a string (e.g., `*.js`) which is matched using [minimatch](https://github.com/isaacs/minimatch), so go there for more
  83. information.
  84. Globstars (`**`) are not supported since specifying a recursive pattern for an already recursive function doesn't make sense.
  85. Negated globs (as explained in the minimatch documentation) are allowed, e.g., `!*.txt` matches everything but text files.
  86. - **array of glob strings**: either need to be all inclusive or all exclusive (negated) patterns otherwise an error is thrown.
  87. `[ '*.json', '*.js' ]` includes all JavaScript and Json files.
  88. `[ '!.git', '!node_modules' ]` includes all directories except the '.git' and 'node_modules'.
  89. Directories that do not pass a filter will not be recursed into.
  90. ## Callback API
  91. Although the stream api is recommended, readdirp also exposes a callback based api.
  92. ***readdirp (options, callback1 [, callback2])***
  93. If callback2 is given, callback1 functions as the **fileProcessed** callback, and callback2 as the **allProcessed** callback.
  94. If only callback1 is given, it functions as the **allProcessed** callback.
  95. ### allProcessed
  96. - function with err and res parameters, e.g., `function (err, res) { ... }`
  97. - **err**: array of errors that occurred during the operation, **res may still be present, even if errors occurred**
  98. - **res**: collection of file/directory [entry infos](#entry-info)
  99. ### fileProcessed
  100. - function with [entry info](#entry-info) parameter e.g., `function (entryInfo) { ... }`
  101. # More Examples
  102. `on('error', ..)`, `on('warn', ..)` and `on('end', ..)` handling omitted for brevity
  103. ```javascript
  104. var readdirp = require('readdirp');
  105. // Glob file filter
  106. readdirp({ root: './test/bed', fileFilter: '*.js' })
  107. .on('data', function (entry) {
  108. // do something with each JavaScript file entry
  109. });
  110. // Combined glob file filters
  111. readdirp({ root: './test/bed', fileFilter: [ '*.js', '*.json' ] })
  112. .on('data', function (entry) {
  113. // do something with each JavaScript and Json file entry
  114. });
  115. // Combined negated directory filters
  116. readdirp({ root: './test/bed', directoryFilter: [ '!.git', '!*modules' ] })
  117. .on('data', function (entry) {
  118. // do something with each file entry found outside '.git' or any modules directory
  119. });
  120. // Function directory filter
  121. readdirp({ root: './test/bed', directoryFilter: function (di) { return di.name.length === 9; } })
  122. .on('data', function (entry) {
  123. // do something with each file entry found inside directories whose name has length 9
  124. });
  125. // Limiting depth
  126. readdirp({ root: './test/bed', depth: 1 })
  127. .on('data', function (entry) {
  128. // do something with each file entry found up to 1 subdirectory deep
  129. });
  130. // callback api
  131. readdirp({ root: '.' }, function(fileInfo) {
  132. // do something with file entry here
  133. }, function (err, res) {
  134. // all done, move on or do final step for all file entries here
  135. });
  136. ```
  137. Try more examples by following [instructions](https://github.com/paulmillr/readdirp/blob/master/examples/Readme.md)
  138. on how to get going.
  139. ## tests
  140. The [readdirp tests](https://github.com/paulmillr/readdirp/blob/master/test/readdirp.js) also will give you a good idea on
  141. how things work.