{"id":13603060,"url":"https://github.com/filerjs/filer","last_synced_at":"2026-02-21T08:01:13.030Z","repository":{"id":5067553,"uuid":"6229442","full_name":"filerjs/filer","owner":"filerjs","description":"Node-like file system for browsers","archived":false,"fork":false,"pushed_at":"2023-03-04T02:44:45.000Z","size":10838,"stargazers_count":638,"open_issues_count":141,"forks_count":156,"subscribers_count":10,"default_branch":"master","last_synced_at":"2026-01-23T17:13:29.983Z","etag":null,"topics":["browser","file","filesystem","fs","indexeddb","nodejs","posix"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-2-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/filerjs.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2012-10-15T15:34:22.000Z","updated_at":"2026-01-16T20:16:15.000Z","dependencies_parsed_at":"2023-07-05T20:46:07.879Z","dependency_job_id":null,"html_url":"https://github.com/filerjs/filer","commit_stats":{"total_commits":858,"total_committers":114,"mean_commits":7.526315789473684,"dds":0.627039627039627,"last_synced_commit":"4f4015a4f7e47ba808c7defd4b2293fce2408b73"},"previous_names":["js-platform/filer"],"tags_count":47,"template":false,"template_full_name":null,"purl":"pkg:github/filerjs/filer","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/filerjs%2Ffiler","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/filerjs%2Ffiler/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/filerjs%2Ffiler/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/filerjs%2Ffiler/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/filerjs","download_url":"https://codeload.github.com/filerjs/filer/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/filerjs%2Ffiler/sbom","scorecard":{"id":399496,"data":{"date":"2025-08-11","repo":{"name":"github.com/filerjs/filer","commit":"4f4015a4f7e47ba808c7defd4b2293fce2408b73"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":2.9,"checks":[{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Warn: no topLevel permission defined: .github/workflows/node-js-ci.yml:1","Info: no jobLevel write permissions found"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Code-Review","score":4,"reason":"Found 6/14 approved changesets -- score normalized to 4","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Pinned-Dependencies","score":0,"reason":"dependency not pinned by hash detected -- score normalized to 0","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/node-js-ci.yml:21: update your workflow using https://app.stepsecurity.io/secureworkflow/filerjs/filer/node-js-ci.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/node-js-ci.yml:23: update your workflow using https://app.stepsecurity.io/secureworkflow/filerjs/filer/node-js-ci.yml/master?enable=pin","Warn: npmCommand not pinned by hash: .github/workflows/node-js-ci.yml:27","Info:   0 out of   2 GitHub-owned GitHubAction dependencies pinned","Info:   0 out of   1 npmCommand dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: BSD 2-Clause \"Simplified\" License: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'","Warn: branch protection not enabled for branch 'develop'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 22 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Vulnerabilities","score":0,"reason":"74 existing vulnerabilities detected","details":["Warn: Project is vulnerable to: GHSA-968p-4wvh-cqc8","Warn: Project is vulnerable to: GHSA-67hx-6x53-jw92","Warn: Project is vulnerable to: GHSA-h5c3-5r3r-rr8q","Warn: Project is vulnerable to: GHSA-rmvr-2pp2-xj38","Warn: Project is vulnerable to: GHSA-xx4v-prfh-6cgc","Warn: Project is vulnerable to: GHSA-93q8-gq69-wqmw","Warn: Project is vulnerable to: GHSA-qwcr-r2fm-qrc7","Warn: Project is vulnerable to: GHSA-v6h2-p8h4-qcjw","Warn: Project is vulnerable to: GHSA-grv7-fg5c-xmjg","Warn: Project is vulnerable to: GHSA-x9w5-v3q2-3rhw","Warn: Project is vulnerable to: GHSA-pxg6-pf52-xh8x","Warn: Project is vulnerable to: GHSA-3xgq-45jj-v275","Warn: Project is vulnerable to: GHSA-gxpj-cx7g-858c","Warn: Project is vulnerable to: GHSA-w573-4hg7-7wgq","Warn: Project is vulnerable to: GHSA-434g-2637-qmqr","Warn: Project is vulnerable to: GHSA-49q7-c7j4-3p7m","Warn: Project is vulnerable to: GHSA-977x-g7h5-7qgw","Warn: Project is vulnerable to: GHSA-f7q4-pwc6-w24p","Warn: Project is vulnerable to: GHSA-fc9h-whq2-v747","Warn: Project is vulnerable to: GHSA-vjh7-7g9h-fjfh","Warn: Project is vulnerable to: GHSA-r7qp-cfhv-p84w","Warn: Project is vulnerable to: GHSA-q9mw-68c2-j6m5","Warn: Project is vulnerable to: GHSA-jchw-25xp-jwwc","Warn: Project is vulnerable to: GHSA-cxjh-pqwp-8mfp","Warn: Project is vulnerable to: GHSA-fjxv-7rqg-78g4","Warn: Project is vulnerable to: GHSA-4q6p-r6v2-jvc5","Warn: Project is vulnerable to: GHSA-pfrx-2q88-qq97","Warn: Project is vulnerable to: GHSA-rc47-6667-2j5j","Warn: Project is vulnerable to: GHSA-896r-f27r-55mw","Warn: Project is vulnerable to: GHSA-9c47-m6qq-7p4h","Warn: Project is vulnerable to: GHSA-rc3x-jf5g-xvc5","Warn: Project is vulnerable to: GHSA-952p-6rrq-rcjv","Warn: Project is vulnerable to: GHSA-f8q6-p94x-37v3","Warn: Project is vulnerable to: GHSA-xvch-5gv4-984h","Warn: Project is vulnerable to: GHSA-qrpm-p2h7-hrv2","Warn: Project is vulnerable to: GHSA-mwcw-c2x4-8c55","Warn: Project is vulnerable to: GHSA-r683-j2x4-v87g","Warn: Project is vulnerable to: GHSA-5rrq-pxf6-6jx5","Warn: Project is vulnerable to: GHSA-8fr3-hfg3-gpgp","Warn: Project is vulnerable to: GHSA-gf8q-jrpm-jvxq","Warn: Project is vulnerable to: GHSA-2r2c-g63r-vccr","Warn: Project is vulnerable to: GHSA-cfm4-qjh2-4765","Warn: Project is vulnerable to: GHSA-x4jg-mjrx-434g","Warn: Project is vulnerable to: GHSA-rp65-9cf3-cjxr","Warn: Project is vulnerable to: GHSA-3j8f-xvm3-ffx4","Warn: Project is vulnerable to: GHSA-4p35-cfcx-8653","Warn: Project is vulnerable to: GHSA-7f3x-x4pr-wqhj","Warn: Project is vulnerable to: GHSA-jpp7-7chh-cf67","Warn: Project is vulnerable to: GHSA-q6wq-5p59-983w","Warn: Project is vulnerable to: GHSA-j9fq-vwqv-2fm2","Warn: Project is vulnerable to: GHSA-pqw5-jmp5-px4v","Warn: Project is vulnerable to: GHSA-h7cp-r72f-jxh6","Warn: Project is vulnerable to: GHSA-v62p-rq8g-8h59","Warn: Project is vulnerable to: GHSA-566m-qj78-rww5","Warn: Project is vulnerable to: GHSA-7fh5-64p2-3v2j","Warn: Project is vulnerable to: GHSA-hwj9-h5mp-3pm3","Warn: Project is vulnerable to: GHSA-hrpp-h998-j3pp","Warn: Project is vulnerable to: GHSA-p8p7-x288-28g6","Warn: Project is vulnerable to: GHSA-c2qf-rxjj-qqgw","Warn: Project is vulnerable to: GHSA-m6fv-jmcg-4jfg","Warn: Project is vulnerable to: GHSA-76p7-773f-r4q5","Warn: Project is vulnerable to: GHSA-cm22-4g7w-348p","Warn: Project is vulnerable to: GHSA-4rq4-32rv-6wp6","Warn: Project is vulnerable to: GHSA-64g7-mvw6-v9qj","Warn: Project is vulnerable to: GHSA-25hc-qcg6-38wj","Warn: Project is vulnerable to: GHSA-qm95-pgcg-qqfq","Warn: Project is vulnerable to: GHSA-cqmj-92xf-r6r9","Warn: Project is vulnerable to: GHSA-4wf5-vphf-c2xc","Warn: Project is vulnerable to: GHSA-52f5-9888-hmc6","Warn: Project is vulnerable to: GHSA-72xf-g2v4-qvf3","Warn: Project is vulnerable to: GHSA-fhg7-m89q-25r3","Warn: Project is vulnerable to: GHSA-j8xg-fqg3-53r7","Warn: Project is vulnerable to: GHSA-3h5v-q93c-6h6q","Warn: Project is vulnerable to: GHSA-c4w7-xm78-47vh"],"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}}]},"last_synced_at":"2025-08-18T19:47:17.847Z","repository_id":5067553,"created_at":"2025-08-18T19:47:17.847Z","updated_at":"2025-08-18T19:47:17.847Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29676975,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-21T06:23:40.028Z","status":"ssl_error","status_checked_at":"2026-02-21T06:23:39.222Z","response_time":107,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["browser","file","filesystem","fs","indexeddb","nodejs","posix"],"created_at":"2024-08-01T18:01:47.905Z","updated_at":"2026-02-21T08:01:12.978Z","avatar_url":"https://github.com/filerjs.png","language":"JavaScript","funding_links":[],"categories":["JavaScript","browser"],"sub_categories":[],"readme":"[![NPM](https://nodei.co/npm/filer.png?downloads=true\u0026stars=true)](https://nodei.co/npm/filer/)\n\n[![Build Status](https://secure.travis-ci.org/filerjs/filer.png?branch=develop)](http://travis-ci.org/filerjs/filer) [![codecov](https://codecov.io/gh/filerjs/filer/branch/master/graph/badge.svg)](https://codecov.io/gh/filerjs/filer)\n\n### Filer\n\nFiler is a drop-in replacement for node's `fs` module, a POSIX-like file system\nfor browsers.\n\n### Compatibility\n\nFiler uses [IndexedDB](https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API)\nand is [known to work in the following browsers/versions](https://caniuse.com/#feat=indexeddb):\n\n* node.js: v0.10.*+\n* IE: 10+\n* Edge: 12+\n* Firefox: 10+\n* Chrome: 23+\n* Safari: 10+\n* Opera: 15+\n* iOS: 10+\n* Android Browser: 4.4+\n\n### Contributing\n\nWant to join the fun? We'd love to have you! See [CONTRIBUTING](https://github.com/filerjs/filer/blob/develop/CONTRIBUTING.md).\n\n### How to Get It\n\nFiler can be obtained in a number of ways:\n\n1. Via npm: `npm install filer`\n1. Via unpkg: `\u003cscript src=\"https://unpkg.com/filer\"\u003e\u003c/script\u003e` or specify a version directly, for example: [https://unpkg.com/filer@1.0.1/dist/filer.min.js](https://unpkg.com/filer@1.0.1/dist/filer.min.js)\n\n### Loading and Usage\n\nFiler is built as a UMD module and can therefore be loaded as a CommonJS or AMD module, or used via the global.\n\n```javascript\n// Option 1: Filer loaded via require()\nvar Filer = require('filer');\n\n// Option 2: Filer loaded via RequireJS\nrequirejs.config({\n  baseUrl: '/',\n  paths: {\n    'filer': 'filer/dist/filer'\n  }\n});\nrequirejs(['filer'], function(Filer) {...}\n\n// Option 3: Filer on global\nvar Filer = window.Filer;\n```\n\n### Webpack Plugin\n\nFiler can be used as a drop-in replacement for the node.js [fs](http://nodejs.org/api/fs.html) and\n[path](http://nodejs.org/api/path.html) modules. For convenience, filer provides a webpack plugin which\nwill shim the desired node.js functionality. This plugin can be used by inserting the following into\nyour webpack config:\n\n```javascript\n// webpack.config.js\nvar { FilerWebpackPlugin } = require('filer/webpack');\n\nmodule.exports = {\n  plugins: [\n    new FilerWebpackPlugin(),\n  ],\n}\n```\n\n---\n**NOTE**\n\nPreviously it was recommended to access the `FilerWebpackPlugin` class by importing the main filer module. This was depracated due [this issue](https://github.com/filerjs/filer/issues/790). For anyone using ***filer version 1.4.0 or earlier***, please import the plugin class like this:\n\n```javascript\nvar FilerWebpackPlugin = require('filer/src/webpack-plugin');\n```\n\n---\n\nYou can then import the node.js [fs](http://nodejs.org/api/fs.html) and [path](http://nodejs.org/api/path.html)\nmodules as normal and `FilerWebpackPlugin` will ensure that webpack will resolve references to these modules to\nthe appropriate filer shims. You will then be able to use these modules as normal (with the exception of the\nsynchronous fs methods e.g. `mkdirSync()`).\n\n```javascript\nimport fs from 'fs';\nimport path from 'path';\n```\n\nThe filer webpack plugin will, by default, shim the [fs](http://nodejs.org/api/fs.html) and\n[path](http://nodejs.org/api/path.html) modules. However, it's behaviour can be customised by passing an\noptions object.\n\n```javascript\n// webpack.config.js\nmodule.exports = {\n  plugins: [\n    new FilerWebpackPlugin({\n      // Options\n    }),\n  ],\n}\n```\n\nThe following options can be passed to the filer webpack plugin:\n\n| Option        | Type    | Optional | Default                                          | Description                                                                                                                                      |\n|---------------|---------|----------|--------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------|\n| filerDir      | string  | yes      | '\\\u003crootDir\\\u003e/node_modules/filer'                 | The directory in which filer is installed.                                                                                                       |\n| shimsDir      | string  | yes      | '\\\u003crootDir\\\u003e/node_modules/filer/shims'           | The directory in which the shims are installed.                                                                                                  |\n| fsProviderDir | string  | yes      | '\\\u003crootDir\\\u003e/node_modules/filer/shims/providers' | The directory in which the shims are located. This option is required when using a custom provider.                                              |\n| shimFs        | boolean | yes      | true                                             | Should the fs module be shimmed.                                                                                                                 |\n| shimPath      | boolean | yes      | true                                             | Should the path module be shimmed.                                                                                                               |\n| fsProvider    | string  | yes      | 'default'                                        | The file system provider to use. Should be one of 'default', 'indexeddb', 'memory', 'custom'. The 'default' option is equivalent to 'indexeddb'. |\n\nNOTE: '\\\u003crootDir\\\u003e' will be resolved to the current working directory.\n\nThough filer also exposes the Buffer object, it is left up to the user to shim this as appropriate. This is because filer offers\nno custom implementation. Currently, filer uses the [node-libs-browser](https://github.com/webpack/node-libs-browser) Buffer implementation\ninternally, though any faithful implementation of the [node.js Buffer object](http://nodejs.org/api/buffer.html) should play nicely\nwith filer.\n\n### Getting Started\n\nFiler is as close to the node.js [fs module](http://nodejs.org/api/fs.html) as possible,\nwith the following differences:\n\n* No synchronous versions of methods (e.g., `mkdir()` but not `mkdirSync()`).\n* No support for stream-based operations (e.g., `fs.ReadStream`, `fs.WriteStream`).\n\nFiler has other features lacking in node.js (e.g., swappable backend\nstorage providers, extended attributes, etc).\n\nLike node.js, the API is asynchronous and most methods expect the caller to provide\na callback function (note: like node.js, Filer will supply one if it's missing).\nErrors are passed to callbacks through the first parameter.  As with node.js,\nthere is no guarantee that file system operations will be executed in the order\nthey are invoked. Ensure proper ordering by chaining operations in callbacks.\n\n### Overview\n\nTo create a new file system or open an existing one, create a new `FileSystem`\ninstance.  By default, a new [IndexedDB](https://developer.mozilla.org/en/docs/IndexedDB)\ndatabase is created for each file system. The file system can also use other\nbackend storage providers, for example `Memory`. See the section on [Storage Providers](#providers).\n\n\u003ca name=\"overviewExample\"\u003e\u003c/a\u003e\n\n```js\nconst { fs, path } = require('filer');\n\nfs.mkdir('/docs', (err) =\u003e {\n  if (err) {\n    return console.error('Unable to create /docs dir', err);\n  }\n  \n  const filename = path.join('/docs', 'first.txt');\n  const data = 'Hello World!\\n';\n\n  fs.writeFile(filename, data, (err) =\u003e {\n    if (err) {\n      return console.error('Unable to write /docs/first.txt', err);\n    }\n\n    fs.stat(filename, (err, stats) =\u003e  {\n      if (err) {\n        return console.error('Unable to stat /docs/first.txt', err);\n      }\n\n      console.log('Stats for /docs/first.txt:', stats);\n    });\n  });\n});\n```\n\nFor a complete list of `FileSystem` methods and examples, see the [FileSystem Instance Methods](#FileSystemMethods)\nsection below.\n\nFiler also includes node's `path` and `Buffer` modules. See the [Filer.Path](#FilerPath) and [Filer.Buffer](#FilerBuffer) sections below.\n\nIn addition, common shell operations (e.g., rm, touch, cat, etc.) are supported via the\n`FileSystemShell` object, which can be obtained from, and used with a `FileSystem`.\nSee the[FileSystemShell](#FileSystemShell) section below.\n\n### API Reference\n\nLike node.js, callbacks for methods that accept them are optional but suggested (i.e., if\nyou omit the callback, errors will be thrown as exceptions). The first callback parameter is\nreserved for passing errors. It will be `null` if no errors occurred and should always be checked.\n\n#### Support for Promises\n\nThe Promise based API mimics the way node [implements](https://nodejs.org/api/fs.html#fs_fs_promises_api) them. Both `Shell` and `FileSystem` now have a `promises` property, which gives access to Promise based versions of methods in addition to the regular callback style methods. Method names are identical to their callback counterparts with the difference that instead of receiving a final argument as a callback, they return a Promise that is resolved or rejected based on the success of method execution.\n\nSee example below:\n\n```javascript\nconst fs = new Filer.FileSystem().promises;\nfs.writeFile('/myfile', 'some data')\n  .then(() =\u003e fs.stat('/myfile'))\n  .then(stats =\u003e { console.log(`stats: ${JSON.stringify(stats)}`); })\n  .catch(err =\u003e { console.error(err); });\n```\n\n#### Filer.FileSystem(options, callback) constructor\n\nIn most cases, using `Filer.fs` will be sufficient, and provide a working filesystem.\nHowever, if you need more control over the filesystem, you can also use the `FileSystem`\nconstructor, invoked to open an existing file system or create a new one.\n\n`Filer.FileSystem()` It accepts two arguments: an `options` object, and an optional\n`callback` function. The `options` object can specify a number of optional arguments,\nincluding:\n\n* `name`: the name of the file system, defaults to `'\"local'`\n* `flags`: an Array of one or more flags to use when creating/opening the file system:\n  * `'FORMAT'` to force Filer to format (i.e., erase) the file system\n  * `'NOCTIME'` to force Filer to not update `ctime` on nodes when metadata changes (i.e., for better performance)\n  * `'NOMTIME'` to force Filer to not update `mtime` on nodes when data changes (i.e., for better performance)\n* `provider`: an explicit storage provider to use for the file system's database context provider. See the section on [Storage Providers](#providers).\n\nThe `callback` function indicates when the file system is ready for use. Depending on the storage provider used, this might\nbe right away, or could take some time. The callback should expect two arguments: first, an `error` argument, which will be\nnull if everything worked; second, an instance, such that you can access the newly ready FileSystem instance. Also users\nshould check the file system's `readyState` and `error` properties to make sure it is usable.\n\n```javascript\nvar fs;\n\nfunction fsReady(err, fs) {\n  if(err) throw err;\n  // Safe to use fs now...\n}\n\nfs = new Filer.FileSystem({\n  name: \"my-filesystem\",\n  flags: [ 'FORMAT' ],\n  provider: new Filer.FileSystem.providers.Memory()\n}, fsReady);\n```\n\nNOTE: if the optional callback argument is not passed to the `FileSystem` constructor,\noperations done on the resulting file system will be queued and run in sequence when\nit becomes ready.\n\n#### Filer.FileSystem.providers - Storage Providers\u003ca name=\"providers\"\u003e\u003c/a\u003e\n\nFiler can be configured to use a number of different storage providers. The provider object encapsulates all aspects of data access, making it possible to swap in different backend storage options.  There are currently 2 providers to choose from:\n\n* `FileSystem.providers.IndexedDB()` - uses IndexedDB\nif necessary\n* `FileSystem.providers.Memory()` - uses memory (not suitable for data that needs to survive the current session)\n\n**NOTE**: previous versions of Filer also supported `FileSystem.providers.WebSQL()` and\n`FileSystem.providers.Fallback()`, which could be used in browsers that supported\nWebSQL but not IndexedDB.  [WebSQL has been deprecated](https://www.w3.org/TR/webdatabase/),\nand this functionality was removed in `v1.0.0`.  If for some reason you still need it, use [`v0.0.44`](https://github.com/filerjs/filer/releases/tag/v0.0.44).\n\nYou can choose your provider when creating a `FileSystem`:\n\n```javascript\nvar FileSystem = Filer.FileSystem;\nvar providers = FileSystem.providers;\n\n// Example 1: Use the default provider (currently IndexedDB)\nvar fs1 = new FileSystem();\n\n// Example 2: Use the Memory provider\nvar fs2 = new FileSystem({ provider: new providers.Memory() });\n```\n\nEvery provider has an `isSupported()` method, which returns `true` if the browser supports this provider:\n\n```javascript\nif( Filer.FileSystem.providers.IndexedDB.isSupported() ) {\n  // IndexedDB provider will work in current environment...\n}\n```\n\nYou can also write your own provider if you need a different backend. See the code in `src/providers` for details.\n\n#### Filer.Buffer\u003ca name=\"FilerBuffer\"\u003e\u003c/a\u003e\n\nWhen reading and writing data, Filer follows node.js and uses [`Buffer`](http://nodejs.org/api/buffer.html).\nWhen in a node.js environment, native `Buffer`s can be used, or Filer.Buffer, which is a shortcut\nto node's `Buffer`.  In a browser, you can use also use `Filer.Buffer`.\n\nNOTE: a `Filer.Buffer` in a browser is really an augmented `Uint8Array` (i.e., the node `Buffer` api\nmethods are added to the instance). See https://github.com/feross/buffer for more details.\n\nNOTE: `Filer.Buffer` currently includes the older, deprecated [constructor functions](https://nodejs.org/api/buffer.html#buffer_new_buffer_array), but these will be removed\nat some point.  You are encouraged to switch to use the newer class methods `Buffer.from()`\nand `Buffer.alloc()`.  See the [node.js Buffer docs](https://nodejs.org/api/buffer.html).\n\n```js\n/* Deprecated - see https://nodejs.org/api/buffer.html#buffer_new_buffer_array */\nnew Buffer(array)\nnew Buffer(arrayBuffer[, byteOffset[, length]])\nnew Buffer(buffer)\nnew Buffer(string[, encoding])\nnew Buffer(size)\n\n/* Use Instead */\nBuffer.from(array)\nBuffer.from(arrayBuffer[, byteOffset[, length]])\nBuffer.from(buffer)\nBuffer.from(string[, encoding])\nBuffer.alloc(size)\nBuffer.allocUnsafe(size)\n```\n\n#### Filer.Path\u003ca name=\"FilerPath\"\u003e\u003c/a\u003e\n\nThe node.js [path module](http://nodejs.org/api/path.html) is available via `Filer.path` or\n`Filer.Path` (both are supported for historical reasons, and to match node). The Filer `path`\nmodule is identical to the node.js version (see [https://github.com/browserify/path-browserify](https://github.com/browserify/path-browserify)), with the following differences:\n\n* The CWD always defaults to `/`\n* No support for Windows style paths (assume you are on a POSIX system)\n* Additional utility methods (see below)\n\n```javascript\nvar path = Filer.path;\nvar dir = path.dirname('/foo/bar/baz/asdf/quux');\n// dir is now '/foo/bar/baz/asdf'\n\nvar base = path.basename('/foo/bar/baz/asdf/quux.html');\n// base is now 'quux.html'\n\nvar ext = path.extname('index.html');\n// ext is now '.html'\n\nvar newpath = path.join('/foo', 'bar', 'baz/asdf', 'quux', '..');\n// new path is now '/foo/bar/baz/asdf'\n```\n\nFor more info see the docs in the [path module](http://nodejs.org/api/path.html) for a particular method:\n* `path.normalize(p)` - NOTE: Filer.Path.normalize does *not* add a trailing slash\n* `path.join([path1], [path2], [...])`\n* `path.resolve([from ...], to)`\n* `path.relative(from, to)`\n* `path.dirname(p)`\n* `path.basename(p, [ext])` - NOTE: Filer.Path.basename will return `'/'` vs. `''`\n* `path.extname(p)`\n* `path.sep`\n* `path.delimiter`\n\nFiler.Path also includes the following extra methods:\n\n* `isNull(p)` returns `true` or `false` if the path contains a null character (`'\\u0000'`)\n* `addTrailing(p)` returns the path `p` with a single trailing slash added\n* `removeTrailing(p)` returns the path `p` with trailing slash(es) removed\n\n[As with node.js](https://nodejs.org/api/fs.html#fs_file_paths), all methods below that\naccept a `path` argument as a `String` can also take a [`file://` URL](https://nodejs.org/api/fs.html#fs_url_object_support)\nor a `Buffer`. For example, all of the following cases will work the same way with Filer:\n\n```js\n// 1. path as a String\nfs.writeFile('/dir/file.txt', 'data', function(err) {...});\n\n// 2. path as a URL\nfs.writeFile(new URL('file:///dir/file.txt'), 'data', function(err) {...});\n\n// 3. path as a Buffer\nfs.writeFile(Buffer.from('/dir/file.txt'), 'data', function(err) {...});\n```\n\n#### Filer.Errors\u003ca name=\"Errors\"\u003e\u003c/a\u003e\n\nThe error objects used internally by Filer are also exposed via the `Filer.Errors` object. As much as possible\nthese match their node.js counterparts, with a few Filer-specifc additions.\nSee [src/errors.js](https://github.com/filerjs/filer/blob/develop/src/errors.js) for the complete\nlist. Errors can be used, or compared, like so:\n\nExamples:\n\n```javascript\n// Example 1: create an EExist error\nvar err1 = new Filer.Errors.EEXIST();\nvar err2 = new Filer.Errors[47];\n\n// Example 2: compare an error to see if it is EInvalid\nfunction callback(err) {\n  if(err instanceof Filer.Errors.EINVAL){\n    ...\n  }\n\n  // Or compare the error's code\n  if(err.code === 'EINVAL') {\n    ...\n  }\n}\n\n// Example 4: compare an error using errno\nfunction callback(err) {\n  if(err.errno === 47){\n    ...\n  }\n\n// Example 5: display the error message\nconsole.log(err.message);\n```\n\n### FileSystem Instance Methods\u003ca name=\"FileSystemMethods\"\u003e\u003c/a\u003e\n\nOnce a `FileSystem` is created, it has the following methods. NOTE: code examples below assume\na `FileSystem` instance named `fs` has been created like so:\n\n```javascript\n// 1. Using Filer.fs for a default filesystem\nconst { fs } = require('filer');\n\n// 2. Or via the FileSystem constructor with specified options\nconst fs = new Filer.FileSystem(options, callback);\n```\n\n* [fs.rename(oldPath, newPath, callback)](#rename)\n* [fs.ftruncate(fd, len, callback)](#ftruncate)\n* [fs.truncate(path, len, callback)](#truncate)\n* [fs.stat(path, callback)](#stat)\n* [fs.fstat(fd, callback)](#fstat)\n* [fs.lstat(path, callback)](#lstat)\n* [fs.exists(path, callback)](#exists)\n* [fs.link(srcpath, dstpath, callback)](#link)\n* [fs.symlink(srcpath, dstpath, [type], callback)](#symlink)\n* [fs.readlink(path, callback)](#readlink)\n* [fs.realpath(path, [cache], callback)](#realpath)\n* [fs.unlink(path, callback)](#unlink)\n* [fs.mknod(path, mode, callback)](#mknod)\n* [fs.rmdir(path, callback)](#rmdir)\n* [fs.mkdir(path, [mode], callback)](#mkdir)\n* [fs.access(path, [mode], callback)](#access)\n* [fs.mkdtemp(path, [options], callback)](#mkdtemp)\n* [fs.readdir(path, callback)](#readdir)\n* [fs.close(fd, callback)](#close)\n* [fs.open(path, flags, [mode], callback)](#open)\n* [fs.utimes(path, atime, mtime, callback)](#utimes)\n* [fs.chown(path, uid, gid, callback)](#chown)\n* [fs.fchown(fd, uid, gid, callback)](#fchown)\n* [fs.chmod(path, mode, callback)](#chmod)\n* [fs.fchmod(fd, mode, callback)](#fchmod)\n* [fs.futimes(fd, atime, mtime, callback)](#fsutimes)\n* [fs.fsync(fd, callback)](#fsync)\n* [fs.write(fd, buffer, offset, length, position, callback)](#write)\n* [fs.read(fd, buffer, offset, length, position, callback)](#read)\n* [fs.readFile(filename, [options], callback)](#readFile)\n* [fs.writeFile(filename, data, [options], callback)](#writeFile)\n* [fs.appendFile(filename, data, [options], callback)](#appendFile)\n* [fs.setxattr(path, name, value, [flag], callback)](#setxattr)\n* [fs.fsetxattr(fd, name, value, [flag], callback)](#fsetxattr)\n* [fs.getxattr(path, name, callback)](#getxattr)\n* [fs.fgetxattr(fd, name, callback)](#fgetxattr)\n* [fs.removexattr(path, name, callback)](#removexattr)\n* [fs.fremovexattr(fd, name, callback)](#fremovexattr)\n* [fs.watch(filename, [options], [listener])](#watch)\n\n#### fs.rename(oldPath, newPath, callback)\u003ca name=\"rename\"\u003e\u003c/a\u003e\n\nRenames the file at `oldPath` to `newPath`. Asynchronous [rename(2)](http://pubs.opengroup.org/onlinepubs/009695399/functions/rename.html).\nCallback gets no additional arguments.\n\nExample:\n\n```javascript\n// Rename myfile.txt to myfile.bak\nfs.rename(\"/myfile.txt\", \"/myfile.bak\", function(err) {\n  if(err) throw err;\n  // myfile.txt is now myfile.bak\n});\n```\n\n#### fs.ftruncate(fd, len, callback)\u003ca name=\"ftruncate\"\u003e\u003c/a\u003e\n\nChange the size of the file represented by the open file descriptor `fd` to be length\n`len` bytes. Asynchronous [ftruncate(2)](http://pubs.opengroup.org/onlinepubs/009695399/functions/ftruncate.html).\nIf the file is larger than `len`, the extra bytes will be discarded; if smaller, its size will\nbe increased, and the extended area will appear as if it were zero-filled. See also [fs.truncate()](#truncate).\n\nExample:\n\n```javascript\n// Create a file, shrink it, expand it.\nvar buffer = Filer.Buffer.from([1, 2, 3, 4, 5, 6, 7, 8]);\n\nfs.open('/myfile', 'w', function(err, fd) {\n  if(err) throw error;\n  fs.write(fd, buffer, 0, buffer.length, 0, function(err, result) {\n    if(err) throw error;\n      fs.ftruncate(fd, 3, function(err) {\n        if(err) throw error;\n        // /myfile is now 3 bytes in length, rest of data discarded\n\n        fs.ftruncate(fd, 50, function(err) {\n          if(err) throw error;\n          // /myfile is now 50 bytes in length, with zero padding at end\n\n          fs.close(fd);\n        });\n      });\n    });\n  });\n});\n```\n\n#### fs.truncate(path, len, callback)\u003ca name=\"truncate\"\u003e\u003c/a\u003e\n\nChange the size of the file at `path` to be length `len` bytes. Asynchronous [truncate(2)](http://pubs.opengroup.org/onlinepubs/009695399/functions/truncate.html). If the file is larger than `len`, the extra bytes will be discarded; if smaller, its size will\nbe increased, and the extended area will appear as if it were zero-filled. See also [fs.ftruncate()](#ftruncate).\n\nExample:\n\n```javascript\n// Create a file, shrink it, expand it.\nvar buffer = Filer.Buffer.from([1, 2, 3, 4, 5, 6, 7, 8]);\n\nfs.open('/myfile', 'w', function(err, fd) {\n  if(err) throw error;\n  fs.write(fd, buffer, 0, buffer.length, 0, function(err, result) {\n    if(err) throw error;\n    fs.close(fd, function(err) {\n      if(err) throw error;\n\n      fs.truncate('/myfile', 3, function(err) {\n        if(err) throw error;\n        // /myfile is now 3 bytes in length, rest of data discarded\n\n        fs.truncate('/myfile', 50, function(err) {\n          if(err) throw error;\n          // /myfile is now 50 bytes in length, with zero padding at end\n\n        });\n      });\n    });\n  });\n});\n```\n\n#### fs.stat(path, callback)\u003ca name=\"stat\"\u003e\u003c/a\u003e\n\nObtain file status about the file at `path`. Asynchronous [stat(2)](http://pubs.opengroup.org/onlinepubs/009695399/functions/stat.html).\nCallback gets `(error, stats)`, where `stats` is an object with the following properties:\n\n```\n{\n  node: \u003cstring\u003e    // internal node id (unique)\n  dev: \u003cstring\u003e     // file system name\n  name: \u003cstring\u003e    // the entry's name (basename)\n  size: \u003cnumber\u003e    // file size in bytes\n  nlinks: \u003cnumber\u003e  // number of links\n  atime: \u003cdate\u003e   // last access time as JS Date Object\n  mtime: \u003cdate\u003e   // last modified time as JS Date Object\n  ctime: \u003cdate\u003e   // creation time as JS Date Object\n  atimeMs: \u003cnumber\u003e   // last access time as Unix Timestamp\n  mtimeMs: \u003cnumber\u003e   // last modified time as Unix Timestamp\n  ctimeMs: \u003cnumber\u003e   // creation time as Unix Timestamp\n  type: \u003cstring\u003e    // file type (FILE, DIRECTORY, SYMLINK),\n  gid: \u003cnumber\u003e     // group name\n  uid: \u003cnumber\u003e     // owner name\n  mode: \u003cnumber\u003e    // permissions\n  version: \u003cnumber\u003e // version of the node\n}\n```\n\nThe following convenience methods are also present on the callback's `stats`:\n\n```\nisFile():             Returns true if the node is a file.\nisDirectory():        Returns true if the node is a directory.\nisBlockDevice():      Not implemented, returns false.\nisCharacterDevice():  Not implemented, returns false.\nisSymbolicLink():     Returns true if the node is a symbolic link.\nisFIFO():             Not implemented, returns false.\nisSocket():           Not implemented, returns false.\n```\n\nIf the file at `path` is a symbolic link, the file to which it links will be used instead.\nTo get the status of a symbolic link file, use [fs.lstat()](#lstat) instead.\n\nExamples:\n\n```javascript\n// Check if a directory exists\nfunction dirExists(path, callback) {\n  fs.stat(path, function(err, stats) {\n    if(err) return callback(err);\n    var exists = stats.type === \"DIRECTORY\";\n    callback(null, exists);\n  });\n};\n\n// Get the size of a file in KB\nfunction fileSize(path, callback) {\n  fs.stat(path, function(err, stats) {\n    if(err) return callback(err);\n    var kb = stats.size / 1000;\n    callback(null, kb);\n  });\n}\n```\n\n#### fs.fstat(fd, callback)\u003ca name=\"fstat\"\u003e\u003c/a\u003e\n\nObtain information about the open file known by the file descriptor `fd`.\nAsynchronous [fstat(2)](http://pubs.opengroup.org/onlinepubs/009695399/functions/fstat.html).\nCallback gets `(error, stats)`. `fstat()` is identical to `stat()`, except that the file to be stat-ed is\nspecified by the open file descriptor `fd` instead of a path.  See also [fs.stat](#stat)\n\nExample:\n\n```javascript\nfs.open(\"/file.txt\", \"r\", function(err, fd) {\n  if(err) throw err;\n  fs.fstat(fd, function(err, stats) {\n    if(err) throw err;\n    // do something with stats object\n    // ...\n    fs.close(fd);\n  });\n});\n```\n\n#### fs.lstat(path, callback)\u003ca name=\"lstat\"\u003e\u003c/a\u003e\n\nObtain information about the file at `path` (i.e., the symbolic link file itself) vs.\nthe destination file to which it links. Asynchronous [lstat(2)](http://pubs.opengroup.org/onlinepubs/009695399/functions/lstat.html).\nCallback gets `(error, stats)`. See also [fs.stat](#stat).\n\nExample:\n\n```javascript\n// Create a symbolic link, /data/logs/current to /data/logs/august\n// and get info about the symbolic link file, and linked file.\nfs.link(\"/data/logs/august\", \"/data/logs/current\", function(err) {\n  if(err) throw err;\n\n  // Get status of linked file, /data/logs/august\n  fs.stat(\"/data/logs/current\", function(err, stats) {\n    if(err) throw err;\n    // Size of /data/logs/august\n    var size = stats.size;\n  });\n\n  // Get status of symbolic link file itself\n  fs.lstat(\"/data/logs/current\", function(err, stats) {\n    if(err) throw err;\n    // Size of /data/logs/current\n    var size = stats.size;\n  });\n});\n```\n\n#### fs.exists(path, callback)\u003ca name=\"exists\"\u003e\u003c/a\u003e\n\nTest whether or not the given path exists by checking with the file system.\nThen call the callback argument with either true or false.\n\nExample:\n\n```javascript\n//Test if the file exists\nfs.exists('/myfile', function (exists) {\n  console.log(exists ? \"file exists\" : \"file not found\");\n});\n```\n\nfs.exists() is an anachronism and exists only for historical reasons. There should almost never be a reason to use it in your own code.\n\nIn particular, checking if a file exists before opening it is an anti-pattern that leaves you vulnerable to race conditions: another process may remove the file between the calls to fs.exists() and fs.open(). Just open the file and handle the error when it's not there.\n\n#### fs.link(srcPath, dstPath, callback)\u003ca name=\"link\"\u003e\u003c/a\u003e\n\nCreate a (hard) link to the file at `srcPath` named `dstPath`. Asynchronous [link(2)](http://pubs.opengroup.org/onlinepubs/009695399/functions/link.html). Callback gets no additional arguments. Links are directory entries that point to the same file node.\n\nExample:\n\n```javascript\nfs.link('/logs/august.log', '/logs/current', function(err) {\n  if(err) throw err;\n  fs.readFile('/logs/current', 'utf8', function(err, data) {\n    // data is the contents of /logs/august.log\n    var currentLog = data;\n  });\n});\n```\n\n#### fs.symlink(srcPath, dstPath, [type], callback)\u003ca name=\"symlink\"\u003e\u003c/a\u003e\n\nCreate a symbolic link to the file at `dstPath` containing the path `srcPath`. Asynchronous [symlink(2)](http://pubs.opengroup.org/onlinepubs/009695399/functions/symlink.html). Callback gets no additional arguments.\nSymbolic links are files that point to other paths.\n\nNOTE: Filer allows for, but ignores the optional `type` parameter used in node.js.\nThe `srcPath` may be a relative path, which will be resolved relative to `dstPath`\n\nExample:\n\n```javascript\n// Absolute path\nfs.symlink('/logs/august.log', '/logs/current', function(err) {\n  if(err) throw err;\n  fs.readFile('/logs/current', 'utf8', function(err, data) {\n    // data is the contents of /logs/august.log\n    var currentLog = data;\n  });\n});\n\n// Relative path\nfs.symlink('../file', '/dir/symlink', function(err) {\n  if(err) throw err;\n  // The /dir/symlink file is now a symlink to /file\n});\n```\n\n#### fs.readlink(path, callback)\u003ca name=\"readlink\"\u003e\u003c/a\u003e\n\nReads the contents of a symbolic link. Asynchronous [readlink(2)](http://pubs.opengroup.org/onlinepubs/009695399/functions/readlink.html).\nCallback gets `(error, linkContents)`, where `linkContents` is a string\ncontaining the symbolic link's link path.  If the original `srcPath` given\nto `symlink()` was a relative path, it will be fully resolved relative\nto `dstPath` when returned by `readlink()`.\n\nExample:\n\n```javascript\nfs.symlink('/logs/august.log', '/logs/current', function(error) {\n  if(error) throw error;\n\n  fs.readlink('/logs/current', function(error, linkContents) {\n    // linkContents is now '/logs/august.log'\n  });\n});\n```\n\n#### fs.realpath(path, [cache], callback)\u003ca name=\"realpath\"\u003e\u003c/a\u003e\n\nNOTE: Not implemented, see https://github.com/filerjs/filer/issues/85\n\n#### fs.unlink(path, callback)\u003ca name=\"unlink\"\u003e\u003c/a\u003e\n\nRemoves the directory entry located at `path`. Asynchronous [unlink(2)](http://pubs.opengroup.org/onlinepubs/009695399/functions/unlink.html).\nCallback gets no additional arguments. If `path` names a symbolic link, the symbolic link will be removed\n(i.e., not the linked file). Otherwise, the filed named by `path` will be removed (i.e., deleted).\n\nExample:\n\n```javascript\n// Delete regular file /backup.old\nfs.unlink('/backup.old', function(err) {\n  if(err) throw err;\n  // /backup.old is now removed\n});\n```\n\n#### fs.mknod(path, mode, callback)\u003ca name=\"mknod\"\u003e\u003c/a\u003e\n\nCreates a node at `path` based on the mode passed which is either `FILE` or `DIRECTORY`. Asynchronous [mknod(2)](http://pubs.opengroup.org/onlinepubs/009695399/functions/mknod.html). Callback gets no additional arguments.\n\nExample:\n\n```javascript\n// Create a /dir directory\nfs.mknod('/dir', 'DIRECTORY', function(err) {\n  if(err) throw err;\n  // /dir is now created\n\n  // Create a file inside /dir\n  fs.mknod('/dir/myfile', 'FILE', function(err) {\n    if(err) throw err;\n    // /dir/myfile now exists\n  });\n});\n```\n\n#### fs.rmdir(path, callback)\u003ca name=\"rmdir\"\u003e\u003c/a\u003e\n\nRemoves the directory at `path`. Asynchronous [rmdir(2)](http://pubs.opengroup.org/onlinepubs/009695399/functions/rmdir.html).\nCallback gets no additional arguments. The operation will fail if the directory at `path` is not empty.\n\nExample:\n\n```javascript\n/**\n * Given the following dir structure, remove docs/\n *  /docs\n *    a.txt\n */\n\n// Start by deleting the files in docs/, then remove docs/\nfs.unlink('/docs/a.txt', function(err) {\n  if(err) throw err;\n  fs.rmdir('/docs', function(err) {\n    if(err) throw err;\n  });\n});\n```\n\n#### fs.mkdir(path, [mode], callback)\u003ca name=\"mkdir\"\u003e\u003c/a\u003e\n\nMakes a directory with name supplied in `path` argument. Asynchronous [mkdir(2)](http://pubs.opengroup.org/onlinepubs/009695399/functions/mkdir.html). Callback gets no additional arguments.\n\nNOTE: Filer allows for, but ignores the optional `mode` argument used in node.js.\n\nExample:\n\n```javascript\n// Create /home and then /home/carl directories\nfs.mkdir('/home', function(err) {\n  if(err) throw err;\n\n  fs.mkdir('/home/carl', function(err) {\n    if(err) throw err;\n    // directory /home/carl now exists\n  });\n});\n```\n\n#### fs.access(path, [mode], callback)\u003ca name=\"access\"\u003e\u003c/a\u003e\n\nTests a user's permissions for the file or directory supplied in `path` argument. Asynchronous [access(2)](http://pubs.opengroup.org/onlinepubs/009695399/functions/access.html). Callback gets no additional arguments. The `mode` argument can be one of the following (constants are available on `fs.constants` and `fs`):\n\n* `F_OK`: Test for existence of file.\n* `R_OK`: Test whether the file exists and grants read permission.\n* `W_OK`: Test whether the file exists and grants write permission.\n* `X_OK`: Test whether the file exists and grants execute permission.\n\nNOTE: you can also create a mask consisting of the bitwise OR of two or more values (e.g. `fs.constants.W_OK | fs.constants.R_OK`).\n\nExample:\n\n```javascript\n// Check if the file exists in the current directory.\nfs.access(file, fs.F_OK, function(err) {\n  console.log(`${file} ${err ? 'does not exist' : 'exists'}`);\n});\n```\n\n#### fs.mkdtemp(prefix, options, callback)\u003ca name=\"mkdtemp\"\u003e\u003c/a\u003e\n\nMakes a temporary directory with prefix supplied in `path` argument. Method will append six random characters directly to the prefix. Asynchronous. Callback gets `(error, path)`, where path is the path to the created directory.\n\nNOTE: Filer allows for, but ignores the optional `options` argument used in node.js.\n\nExample:\n\n```javascript\n// Create tmp directory with prefix foo\nfs.mkdtemp(\"/foo-\", function (error, path) {\n    // A new folder foo-xxxxxx will be created. Path contains a path to created folder.    \n});\n\nfs.mkdtemp(\"/myDir/tmp\", function (error, path) {\n    // Will create a new folder tmpxxxxxx inside myDir directory. \n    // Will throw error if myDir does not exist    \n});\n```\n\n#### fs.readdir(path, [options], callback)\u003ca name=\"readdir\"\u003e\u003c/a\u003e\n\nReads the contents of a directory. Asynchronous [readdir(3)](http://pubs.opengroup.org/onlinepubs/009695399/functions/readdir.html).\nCallback gets `(error, files)`, where `files` is an array containing the names of each directory entry (i.e., file, directory, link) in the directory, excluding `.` and `..`.\n\nExample:\n\n```javascript\n/**\n * Given the following dir structure:\n *  /docs\n *    a.txt\n *    b.txt\n *    c/\n */\nfs.readdir('/docs', function(err, files) {\n  if(err) throw err;\n  // files now contains ['a.txt', 'b.txt', 'c']\n});\n```\n\nOptionally accepts an options parameter, which can be either an encoding (e.g. \"utf8\") or an object with optional properties `encoding` and `withFileTypes`.\n\nThe `encoding` property is a `string` which will determine the character encoding to use for the names of each directory entry. The `withFileTypes` property is a `boolean` which defaults to `false`. If `true`, this method will return an array of [fs.Dirent](https://nodejs.org/api/fs.html#fs_class_fs_dirent) objects.\n\nThe `name` property on the [fs.Dirent](https://nodejs.org/api/fs.html#fs_class_fs_dirent) objects will be encoded using the specified character encoding.\n\n#### fs.close(fd, callback)\u003ca name=\"close\"\u003e\u003c/a\u003e\n\nCloses a file descriptor. Asynchronous [close(2)](http://pubs.opengroup.org/onlinepubs/009695399/functions/close.html).\nCallback gets no additional arguments.\n\nExample:\n\n```javascript\nfs.open('/myfile', 'w', function(err, fd) {\n  if(err) throw error;\n\n  // Do something with open file descriptor `fd`\n\n  // Close file descriptor when done\n  fs.close(fd);\n});\n```\n\n#### fs.open(path, flags, [mode], callback)\u003ca name=\"open\"\u003e\u003c/a\u003e\n\nOpens a file. Asynchronous [open(2)](http://pubs.opengroup.org/onlinepubs/009695399/functions/open.html).\nCallback gets `(error, fd)`, where `fd` is the file descriptor. The `flags` argument can be:\n\n* `'r'`: Open file for reading. An exception occurs if the file does not exist.\n* `'r+'`: Open file for reading and writing. An exception occurs if the file does not exist.\n* `'w'`: Open file for writing. The file is created (if it does not exist) or truncated (if it exists).\n* `'w+'`: Open file for reading and writing. The file is created (if it does not exist) or truncated (if it exists).\n* `'a'`: Open file for appending. The file is created if it does not exist.\n* `'a+'`: Open file for reading and appending. The file is created if it does not exist.\n\nNOTE: Filer allows for, but ignores the optional `mode` argument used in node.js.\n\nExample:\n\n```javascript\nfs.open('/myfile', 'w', function(err, fd) {\n  if(err) throw error;\n\n  // Do something with open file descriptor `fd`\n\n  // Close file descriptor when done\n  fs.close(fd);\n});\n```\n\n#### fs.utimes(path, atime, mtime, callback)\u003ca name=\"utimes\"\u003e\u003c/a\u003e\n\nChanges the file timestamps for the file given at path `path`. Asynchronous [utimes(2)](http://pubs.opengroup.org/onlinepubs/009695399/functions/utimes.html). Callback gets no additional arguments. Both `atime` (access time) and `mtime` (modified time) arguments should be a JavaScript Date or Number.\n\nExample:\n\n```javascript\nvar now = Date.now();\nfs.utimes('/myfile.txt', now, now, function(err) {\n  if(err) throw err;\n  // Access Time and Modified Time for /myfile.txt are now updated\n});\n```\n\n#### fs.futimes(fd, atime, mtime, callback)\u003ca name=\"futimes\"\u003e\u003c/a\u003e\n\nChanges the file timestamps for the open file represented by the file descriptor `fd`. Asynchronous [utimes(2)](http://pubs.opengroup.org/onlinepubs/009695399/functions/utimes.html). Callback gets no additional arguments. Both `atime` (access time) and `mtime` (modified time) arguments should be a JavaScript Date or Number.\n\nExample:\n\n```javascript\nfs.open('/myfile.txt', function(err, fd) {\n  if(err) throw err;\n\n  var now = Date.now();\n  fs.futimes(fd, now, now, function(err) {\n    if(err) throw err;\n\n    // Access Time and Modified Time for /myfile.txt are now updated\n\n    fs.close(fd);\n  });\n});\n```\n\n#### fs.chown(path, uid, gid, callback)\u003ca name=\"chown\"\u003e\u003c/a\u003e\n\nChanges the owner and group of a file. Asynchronous [chown(2)](http://pubs.opengroup.org/onlinepubs/009695399/functions/chown.html). Callback gets no additional arguments. Both `uid` (user id) and `gid` (group id) arguments should be a JavaScript Number.  By default, `0x0` is used (i.e., `root:root` ownership).\n\nExample:\n\n```javascript\nfs.chown('/myfile.txt', 500, 500, function(err) {\n  if(err) throw err;\n\n  // /myfile.txt is now owned by user with id 500, group 500\n});\n```\n\n#### fs.fchown(fd, uid, gid, callback)\u003ca name=\"fchown\"\u003e\u003c/a\u003e\n\nChanges the owner and group of a file. Asynchronous [chown(2)](http://pubs.opengroup.org/onlinepubs/009695399/functions/chown.html). Callback gets no additional arguments. Both `uid` (user id) and `gid` (group id) arguments should be a JavaScript Number.  By default, `0x0` is used (i.e., `root:root` ownership).\n\nExample:\n\n```javascript\nfs.open('/myfile.txt', function(err, fd) {\n  if(err) throw err;\n\n  fs.fchown(fd, 500, 500, function(err) {\n    if(err) throw err;\n\n    // /myfile.txt is now owned by user with id 500, group 500\n\n    fs.close(fd);\n  });\n});\n```\n\n#### fs.chmod(path, mode, callback)\u003ca name=\"chmod\"\u003e\u003c/a\u003e\n\nChanges the mode of a file. Asynchronous [chmod(2)](http://pubs.opengroup.org/onlinepubs/009695399/functions/chmod.html). Callback gets no additional arguments. The `mode` argument should be a JavaScript Number, which combines file type and permission information.  Here are a list of common values useful for setting the `mode`:\n\n* File type `S_IFREG=0x8000`\n* Dir type `S_IFDIR=0x4000`\n* Link type `S_IFLNK=0xA000`\n\n* Permissions `755=0x1ED`\n* Permissions `644=0x1A4`\n* Permissions `777=0x1FF`\n* Permissions `666=0x1B6`\n\nBy default, directories use `(0x4000 | 0x1ED)` and files use `(0x8000 | 0x1A4)`.\n\nExample:\n\n```javascript\n// S_IFREG | 0o777\nvar mode = 0x8000 | 0x1FF\nfs.chmod('/myfile.txt', mode, function(err) {\n  if(err) throw err;\n\n  // /myfile.txt is a regular file with permissions 777\n});\n```\n\n#### fs.fchmod(fd, mode, callback)\u003ca name=\"fchmod\"\u003e\u003c/a\u003e\n\nChanges the mode of a file. Asynchronous [chmod(2)](http://pubs.opengroup.org/onlinepubs/009695399/functions/chmod.html). Callback gets no additional arguments. The `mode` argument should be a JavaScript Number, which combines file type and permission information.  By default, `755` (dir) and `644` (file) are used.\n\nExample:\n\n```javascript\nfs.open('/myfile.txt', function(err, fd) {\n  if(err) throw err;\n\n  // S_IFREG | 0o777\n  var mode = 0x8000 | 0x1FF\n  fs.fchmod(fd, mode, function(err) {\n    if(err) throw err;\n\n    // /myfile.txt is a regular file with permissions 777\n\n    fs.close(fd);\n  });\n});\n```\n\n#### fs.fsync(fd, callback)\u003ca name=\"fsync\"\u003e\u003c/a\u003e\n\nSynchronize the data and metadata for the file referred to by `fd` to disk.\nAsynchronous [fsync(2)](http://man7.org/linux/man-pages/man2/fsync.2.html).\nThe callback gets `(error)`.\n\n```js\nfs.open('/myfile', 'r', function(error, fd) {\n  if(err) throw err;\n\n  // Use fd, then sync\n\n  fs.fsync(fd, function(error) {\n    if(err) throw err;\n    fs.close(fd, done);\n  });\n});\n```\n\n#### fs.write(fd, buffer, offset, length, position, callback)\u003ca name=\"write\"\u003e\u003c/a\u003e\n\nWrites bytes from `buffer` to the file specified by `fd`. Asynchronous [write(2), pwrite(2)](http://pubs.opengroup.org/onlinepubs/009695399/functions/write.html). The `offset` and `length` arguments describe the part of the buffer to be written. The `position` refers to the offset from the beginning of the file where this data should be written. If `position` is `null`, the data will be written at the current position. The callback gets `(error, nbytes)`, where `nbytes` is the number of bytes written.\n\nNOTE: Filer currently writes the entire buffer in a single operation. However, future versions may do it in chunks.\n\nExample:\n\n```javascript\n// Create a file with the following bytes.\nvar buffer = Filer.Buffer.from([1, 2, 3, 4, 5, 6, 7, 8]);\n\nfs.open('/myfile', 'w', function(err, fd) {\n  if(err) throw error;\n\n  var expected = buffer.length, written = 0;\n  function writeBytes(offset, position, length) {\n    length = length || buffer.length - written;\n\n    fs.write(fd, buffer, offset, length, position, function(err, nbytes) {\n      if(err) throw error;\n\n      // nbytes is now the number of bytes written, between 0 and buffer.length.\n      // See if we still have more bytes to write.\n      written += nbytes;\n\n      if(written \u003c expected)\n        writeBytes(written, null);\n      else\n        fs.close(fd);\n    });\n  }\n\n  writeBytes(0, 0);\n});\n```\n\n#### fs.read(fd, buffer, offset, length, position, callback)\u003ca name=\"read\"\u003e\u003c/a\u003e\n\nRead bytes from the file specified by `fd` into `buffer`. Asynchronous [read(2), pread(2)](http://pubs.opengroup.org/onlinepubs/009695399/functions/read.html). The `offset` and `length` arguments describe the part of the buffer to be used. The `position` refers to the offset from the beginning of the file where this data should be read. If `position` is `null`, the data will be written at the current position. The callback gets `(error, nbytes)`, where `nbytes` is the number of bytes read.\n\nNOTE: Filer currently reads into the buffer in a single operation. However, future versions may do it in chunks.\n\nExample:\n\n```javascript\nfs.open('/myfile', 'r', function(err, fd) {\n  if(err) throw err;\n\n  // Determine size of file\n  fs.fstat(fd, function(err, stats) {\n    if(err) throw err;\n\n    // Create a buffer large enough to hold the file's contents\n    var nbytes = expected = stats.size;\n    var buffer = Filer.Buffer.alloc(nbytes);\n    var read = 0;\n\n    function readBytes(offset, position, length) {\n      length = length || buffer.length - read;\n\n      fs.read(fd, buffer, offset, length, position, function(err, nbytes) {\n        if(err) throw err;\n\n        // nbytes is now the number of bytes read, between 0 and buffer.length.\n        // See if we still have more bytes to read.\n        read += nbytes;\n\n        if(read \u003c expected)\n          readBytes(read, null);\n        else\n          fs.close(fd);\n      });\n    }\n\n    readBytes(0, 0);\n  });\n});\n```\n\n#### fs.readFile(filename, [options], callback)\u003ca name=\"readFile\"\u003e\u003c/a\u003e\n\nReads the entire contents of a file. The `options` argument is optional, and can take the form `\"utf8\"` (i.e., an encoding) or be an object literal: `{ encoding: \"utf8\", flag: \"r\" }`. If no encoding is specified, the raw binary buffer is returned via the callback. The callback gets `(error, data)`, where data is the contents of the file.\n\nExamples:\n\n```javascript\n// Read UTF8 text file\nfs.readFile('/myfile.txt', 'utf8', function (err, data) {\n  if (err) throw err;\n  // data is now the contents of /myfile.txt (i.e., a String)\n});\n\n// Read binary file\nfs.readFile('/myfile.txt', function (err, data) {\n  if (err) throw err;\n  // data is now the contents of /myfile.txt (i.e., a Buffer with the bytes)\n});\n```\n\n#### fs.writeFile(filename, data, [options], callback)\u003ca name=\"writeFile\"\u003e\u003c/a\u003e\n\nWrites data to a file. `data` can be a string or `Buffer`, in which case any encoding option is ignored. The `options` argument is optional, and can take the form `\"utf8\"` (i.e., an encoding) or be an object literal: `{ encoding: \"utf8\", flag: \"w\" }`. If no encoding is specified, and `data` is a string, the encoding defaults to `'utf8'`.  The callback gets `(error)`.\n\nExamples:\n\n```javascript\n// Write UTF8 text file\nfs.writeFile('/myfile.txt', \"...data...\", function (err) {\n  if (err) throw err;\n});\n\n// Write binary file\nvar buffer = Filer.Buffer.from([1, 2, 3, 4, 5, 6, 7, 8]);\nfs.writeFile('/myfile', buffer, function (err) {\n  if (err) throw err;\n});\n```\n\n#### fs.appendFile(filename, data, [options], callback)\u003ca name=\"appendFile\"\u003e\u003c/a\u003e\n\nWrites data to the end of a file. `data` can be a string or a `Buffer`, in which case any encoding option is ignored. The `options` argument is optional, and can take the form `\"utf8\"` (i.e., an encoding) or be an object literal: `{ encoding: \"utf8\", flag: \"w\" }`. If no encoding is specified, and `data` is a string, the encoding defaults to `'utf8'`.  The callback gets `(error)`.\n\nExamples:\n\n```javascript\n// Append UTF8 text file\nfs.writeFile('/myfile.txt', \"More...\", function (err) {\n\tif (err) throw err;\n});\nfs.appendFile('/myfile.txt', \"Data...\", function (err) {\n  if (err) throw err;\n});\n// '/myfile.txt' would now read out 'More...Data...'\n\n// Append binary file\nvar data = Filer.Buffer.from([1, 2, 3, 4]);\nvar more = Filer.Buffer.from([5, 6, 7, 8]);\n\nfs.writeFile('/myfile', data, function (err) {\n  if (err) throw err;\n\n  fs.appendFile('/myfile', more, function (err) {\n    if (err) throw err;\n\n    // '/myfile' would now contain [1, 2, 3, 4, 5, 6, 7, 8]\n  });\n});\n```\n\n#### fs.setxattr(path, name, value, [flag], callback)\u003ca name=\"setxattr\"\u003e\u003c/a\u003e\n\nSets an extended attribute of a file or directory named `path`. Asynchronous [setxattr(2)](http://man7.org/linux/man-pages/man2/setxattr.2.html).\nThe optional `flag` parameter can be set to the following:\n* `XATTR_CREATE`: ensures that the extended attribute with the given name will be new and not previously set. If an attribute with the given name already exists, it will return an `EExists` error to the callback.\n* `XATTR_REPLACE`: ensures that an extended attribute with the given name already exists. If an attribute with the given name does not exist, it will return an `ENoAttr` error to the callback.\n\nCallback gets no additional arguments.\n\nExample:\n\n```javascript\nfs.writeFile('/myfile', 'data', function(err) {\n  if(err) throw err;\n\n  // Set a simple extended attribute on /myfile\n  fs.setxattr('/myfile', 'extra', 'some-information', function(err) {\n    if(err) throw err;\n\n    // /myfile now has an added attribute of extra='some-information'\n  });\n\n  // Set a complex object attribute on /myfile\n  fs.setxattr('/myfile', 'extra-complex', { key1: 'value1', key2: 103 }, function(err) {\n    if(err) throw err;\n\n    // /myfile now has an added attribute of extra={ key1: 'value1', key2: 103 }\n  });\n});\n```\n\n#### fs.fsetxattr(fd, name, value, [flag], callback)\u003ca name=\"fsetxattr\"\u003e\u003c/a\u003e\n\nSets an extended attribute of the file represented by the open file descriptor `fd`. Asynchronous [setxattr(2)](http://man7.org/linux/man-pages/man2/setxattr.2.html).  See `fs.setxattr` for more details. Callback gets no additional arguments.\n\nExample:\n\n```javascript\nfs.open('/myfile', 'w', function(err, fd) {\n  if(err) throw err;\n\n  // Set a simple extended attribute on fd for /myfile\n  fs.fsetxattr(fd, 'extra', 'some-information', function(err) {\n    if(err) throw err;\n\n    // /myfile now has an added attribute of extra='some-information'\n  });\n\n  // Set a complex object attribute on fd for /myfile\n  fs.fsetxattr(fd, 'extra-complex', { key1: 'value1', key2: 103 }, function(err) {\n    if(err) throw err;\n\n    // /myfile now has an added attribute of extra={ key1: 'value1', key2: 103 }\n  });\n\n  fs.close(fd);\n});\n```\n\n#### fs.getxattr(path, name, callback)\u003ca name=\"getxattr\"\u003e\u003c/a\u003e\n\nGets an extended attribute value for a file or directory. Asynchronous [getxattr(2)](http://man7.org/linux/man-pages/man2/getxattr.2.html).\nCallback gets `(error, value)`, where `value` is the value for the extended attribute named `name`.\n\nExample:\n\n```javascript\n// Get the value of the extended attribute on /myfile named `extra`\nfs.getxattr('/myfile', 'extra', function(err, value) {\n  if(err) throw err;\n\n  // `value` is now the value of the extended attribute named `extra` for /myfile\n});\n```\n\n#### fs.fgetxattr(fd, name, callback)\u003ca name=\"fgetxattr\"\u003e\u003c/a\u003e\n\nGets an extended attribute value for the file represented by the open file descriptor `fd`.\nAsynchronous [getxattr(2)](http://man7.org/linux/man-pages/man2/getxattr.2.html).\nSee `fs.getxattr` for more details. Callback gets `(error, value)`, where `value` is the value for the extended attribute named `name`.\n\nExample:\n\n```javascript\n// Get the value of the extended attribute on /myfile named `extra`\nfs.open('/myfile', 'r', function(err, fd) {\n  if(err) throw err;\n\n  fs.fgetxattr(fd, 'extra', function(err, value) {\n    if(err) throw err;\n\n    // `value` is now the value of the extended attribute named `extra` for /myfile\n  });\n\n  fs.close(fd);\n});\n```\n\n#### fs.removexattr(path, name, callback)\u003ca name=\"removexattr\"\u003e\u003c/a\u003e\n\nRemoves the extended attribute identified by `name` for the file given at `path`. Asynchronous [removexattr(2)](http://man7.org/linux/man-pages/man2/removexattr.2.html). Callback gets no additional arguments.\n\nExample:\n\n```javascript\n// Remove an extended attribute on /myfile\nfs.removexattr('/myfile', 'extra', function(err) {\n  if(err) throw err;\n\n  // The `extra` extended attribute on /myfile is now gone\n});\n```\n\n#### fs.fremovexattr(fd, name, callback)\u003ca name=\"fremovexattr\"\u003e\u003c/a\u003e\n\nRemoves the extended attribute identified by `name` for the file represented by the open file descriptor `fd`.\nAsynchronous [removexattr(2)](http://man7.org/linux/man-pages/man2/removexattr.2.html). See `fs.removexattr` for more details.\nCallback gets no additional arguments.\n\nExample:\n\n```javascript\n// Remove an extended attribute on /myfile\nfs.open('/myfile', 'r', function(err, fd) {\n  if(err) throw err;\n\n  fs.fremovexattr(fd, 'extra', function(err) {\n    if(err) throw err;\n\n    // The `extra` extended attribute on /myfile is now gone\n  });\n\n  fs.close(fd);\n});\n```\n\n#### fs.watch(filename, [options], [listener])\u003ca name=\"watch\"\u003e\u003c/a\u003e\n\nWatch for changes to a file or directory at `filename`. The object returned is an `FSWatcher`,\nwhich is an [`EventEmitter`](http://nodejs.org/api/events.html) with the following additional method:\n\n* `close()` - stops listening for changes, and removes all listeners from this instance. Use this\nto stop watching a file or directory after calling `fs.watch()`.\n\nThe only supported option is `recursive`, which if `true` will cause a watch to be placed\non a directory, and all sub-directories and files beneath it.\n\nThe `listener` callback gets two arguments `(event, filename)`. `event` is either `'rename'` or `'change'`,\n(currenty only `'rename'` is supported) and `filename` is the name of the file/dir which triggered the event.\n\nUnlike node.js, all watch events return a path. Also, all returned paths are absolute from the root\nvs. just a relative filename.\n\nExamples:\n\n```javascript\n// Example 1: create a watcher to see when a file is created\nvar watcher = fs.watch('/myfile', function(event, filename) {\n  // event could be 'change' or 'rename' and filename will be '/myfile'\n  // Stop watching for changes\n  watcher.close();\n});\nfs.writeFile('/myfile', 'data');\n\n// Example 2: add the listener via watcher.on()\nvar watcher = fs.watch('/myfile2');\nwatcher.on('change', function(event, filename) {\n  // event will be 'change' and filename will be '/myfile2'\n  // Stop watching for changes\n  watcher.close();\n});\nfs.writeFile('/myfile2', 'data2');\n\n// Example 3: recursive watch on /data dir\nvar watcher = fs.watch('/data', { recursive: true }, function(event, filename) {\n  // event could be 'change' or 'rename' and filename will be '/data/subdir/file'\n  // Stop watching for changes\n  watcher.close();\n});\nfs.writeFile('/data/subdir/file', 'data');\n```\n\n### FileSystemShell\u003ca name=\"FileSystemShell\"\u003e\u003c/a\u003e\n\nMany common file system shell operations are available by using a `FileSystemShell` object.\nThe `FileSystemShell` is used in conjunction with a `FileSystem`,\nand provides augmented features. Many separate `FileSystemShell` objects can exist per\n`FileSystem`, but each `FileSystemShell` is bound to a single instance of a `FileSystem`\nfor its lifetime.\n\nA `FileSystemShell` is created by instantiating `Filer.FileSystem().Shell`:\n\n```javascript\nvar fs = new Filer.FileSystem();\nvar sh = new fs.Shell(options);\nvar sh2 = new fs.Shell(options);\n// sh and sh2 are two separate shells, each bound to fs\n```\n\nIn addition, the constructor function can be accessed through `Filer`:\n\n```javascript\nvar fs = new Filer.FileSystem();\nvar sh = new fs.Shell();\n\nFiler.Shell.prototype.newFunction = ...;\n\nsh.newFunction();\n```\n\nThe `FileSystemShell` can take an optional `options` object. The `options` object\ncan include `env`, which is a set of environment variables. Currently supported variables\ninclude `TMP` (the path to the temporary directory), and `PATH` (the list of known paths) and\nothers may be added in the future. You can also add your own, or update existing variables.\n\n```javascript\nvar fs = new Filer.FileSystem();\nvar sh = new fs.Shell({\n  env: {\n    TMP: '/tempdir',\n    PATH: '/one:/two'\n  }\n});\nvar tempPath = sh.env.get('TMP');\nsh.env.set('TMP', '/newtempdir');\n```\n\nNOTE: unless otherwise stated, all `FileSystemShell` methods can take relative or absolute\npaths. Relative paths are resolved relative to the shell's current working directory (`sh.cwd`).\nThis is different from the `FileSystem`, which requires absolute paths, and has no notion\nof a current working directory.\n\n#### FileSystemShell Properties\n\nA `FileSystemShell` has a number of properties, including:\n* `fs` - (readonly) a reference to the bound `FileSystem`\n* `env` - (readonly) the shell's environment. The shell's environemnt `env` object has `get(name)`\nand `set(name, value)` methods.\n\nExample:\n\n```javascript\nvar fs = new Filer.FileSystem();\nvar sh = new fs.Shell();\nvar p = sh.env.get('PATH');\n\n// Store the current location\nvar before = sh.pwd();\nvar after;\nsh.cd('/newdir', function(err) {\n  if(err) throw err;\n  // Get the new location\n  after = sh.pwd();\n});\n```\n\n#### FileSystemShell Instance Methods\n\nOnce a `FileSystemShell` object is created, it has the following methods. NOTE: code\nexamples below assume a `FileSystemShell` instance named `sh` has been created like so:\n\n```javascript\nvar fs = new Filer.FileSystem();\nvar sh = new fs.Shell();\n```\n\n* [sh.cd(path, callback)](#cd)\n* [sh.pwd()](#pwd)\n* [sh.find(dir, [options], callback)](#find)\n* [sh.ls(dir, [options], callback)](#ls)\n* [sh.exec(path, [args], callback)](#exec)\n* [sh.touch(path, [options], callback)](#touch)\n* [sh.cat(files, callback)](#cat)\n* [sh.rm(path, [options], callback)](#rm)\n* [sh.tempDir(callback)](#tempDir)\n* [sh.mkdirp(path, callback)](#mkdirp)\n\n\n#### sh.cd(path, callback)\u003ca name=\"cd\"\u003e\u003c/a\u003e\n\nChanges the current working directory to the directory at `path`. The callback returns\nan error if `path` does not exist, or is not a directory. Once the callback occurs\nthe shell's cwd is updated to the new path (you can access it via `sh.pwd()`).\n\nExample:\n\n```javascript\nsh.cd('/dir1', function(err) {\n  if(err) throw err;\n  // sh.pwd() is now '/dir1'\n});\n```\n\n#### sh.pwd()\u003ca name=\"pwd\"\u003e\u003c/a\u003e\n\nReturns the shell's current working directory. See [sh.cd()](#cd).\n\n#### sh.find(dir, [options], callback)\u003ca name=\"find\"\u003e\u003c/a\u003e\n\nRecursively walk a directory tree, reporting back all paths that were\nfound along the way. Asynchronous [find(1)](http://pubs.opengroup.org/onlinepubs/9699919799/utilities/find.html\n)\nIf given no options, `find` walks the given dir path\nand the callback gives `function(err, found)`, where `found` is an array of\nall paths discovered during a depth-first walk.\n\nValid options include a `regex` for pattern matching paths, allowing paths\nto be ignored (e.g., ```regex: /\\.bak$/``` to find all `.bak` files). You can\nalso use `name` and `path` to provide a [match pattern](https://github.com/isaacs/minimatch) for the basename and\ndirname respectively (e.g., `{name: '*.js'}` to find all JavaScript files or\n`{path: '*-modules'}` to only look in folders named `base-modules`, `foo-modules`, etc.).\nFinally, you can also provide an `exec` function of the form `function(path, next)` where\n`path` is the current path that was found and matches any provided `regex`\n(NOTE: dir paths have an '/' appended), and `next` is a callback to call\nwhen you are done processing the path.\n\nExample:\n\n```javascript\nfunction processPath(path, next) {\n  // Process the path somehow, in this case we print it.\n  // Dir paths end with /\n  if(path.endsWith('/')) {\n    console.log('Found dir: ' + path);\n  } else {\n    console.log('Found file: ' + path);\n  }\n\n  // All done, let the process continue by invoking second arg:\n  next();\n}\n\n// Get every path (NOTE: no name or regex provided) below the root, depth first\nsh.find('/', {exec: processPath}, function(err, found) {\n  /* find command is finished, `found` contains the flattened list as an Array */\n});\n\n// Find all files that look like map201.jpg, map202.jpg in the /data dir\nsh.find('/data', {regex: /map20\\d\\.jpg$/, exec: processPath}, function(err) {\n  /* find command is finished */\n});\n\n// Find and delete all *.bak files under /app/user\nsh.find('/app/user', {\n  name: '*.bak',\n  exec: function(path, next) {\n    sh.rm(path, next);\n  }\n}, function callback(err, found) {\n  if(err) throw err;\n\n  if(found.length) {\n    console.log('Deleted the following ' + found.length + ' files: ', found);\n  }\n});\n```\n\n#### sh.ls(dir, [options], callback)\u003ca name=\"ls\"\u003e\u003c/a\u003e\n\nGet the listing of a directory, returning an array of directory entries\nin the same form as [fs.stat()](#stat), with the exception that a new Array named\n`contents` is added for directory entries, containing child entries.\n\nBy default `sh.ls()` gives a shallow listing. If you want to follow\ndirectories as they are encountered, use the `recursive=true` option. NOTE:\nyou should not count on the order of the returned entries always being the same.\n\nExample:\n\n```javascript\n/**\n * Given a dir structure of:\n *\n * /dir\n *  file1\n *  file2\n *  dir2/\n *   file3\n */\n\n// Shallow listing\nsh.ls('/dir', function(err, entries) {\n  if(err) throw err;\n  // entries is now an array of 3 file/dir entries under /dir\n});\n\n// Deep listing\nsh.ls('/dir', { recursive: true }, function(err, entries) {\n  if(err) throw err;\n  // entries is now an array of 3 file/dir entries under /dir.\n  // The entry object for '/dir2' also includes a `contents` property,\n  // which is an array of 1 entry element for `file3`.\n});\n```\n\n#### sh.exec(path, [args], callback)\u003ca name=\"exec\"\u003e\u003c/a\u003e\n\nAttempts to execute the .js command located at `path`. The `sh.exec` method\nenables apps to install larger programs into the file system and run them\nlater without having to re-download.  Such commands should be written so as\nto assume the existence of 3 global variables, which will be defined at runtime:\n* `fs` - [FileSystem] the `FileSystem` object bound to this shell.\n* `args` - [Array] a list of any arguments for the command, or the empty list\n* `callback` - [Function] a callback function of the form `function callback(error, result)`\nto call when done.\n\nThe .js command's contents should be the body of a function that\nlooks like this:\n\n```javascript\nfunction(fs, args, callback) {\n//-------------------------commmand code here---------\n// ...\n//----------------------------------------------------\n }\n```\n\nExample:\n\n```javascript\n// Simple command to delete a file.\nvar cmd = \"fs.unlink(args[0], callback);\"\n\n// Write the file to the filesystem\nfs.writeFile('/cmd.js', cmd, callback(err) {\n  if(err) throw err;\n\n  // Execute the command\n  sh.exec('/cmd.js', [ '/file' ], function(err, result) {\n    if(err) throw err;\n  });\n});\n```\n\n#### sh.touch(path, [options], callback)\u003ca name=\"touch\"\u003e\u003c/a\u003e\n\nCreate a file if it does not exist, or update the access and modified\ntimes if it does. Valid options include:\n* `updateOnly` - `true` if the file's access/modified dates are to be updated\nonly (but missing file not to be)\n* `date` - a date to use instead of the current date and time when updating\naccess and modified dates.\n\nExample:\n\n```javascript\nsh.touch('/newfile', function(err) {\n  if(err) throw err;\n\n  fs.exists('/newfile', function(exists) {\n    // exists is now true.\n  }\n});\n```\n\n#### sh.cat(files, callback)\u003ca name=\"cat\"\u003e\u003c/a\u003e\n\nConcatenates multiple files into a single string, with each file\nseparated by a newline character. The `files` argument should be\na String (i.e., path to a single file) or an Array of Strings (i.e.,\nmultiple paths for multiple files).\n\nExample:\n\n```javascript\nsh.cat([ './file1', '../file2' ], function(err, data) {\n  if(err) throw err;\n  // data is now the contents of file1 and file2 joined\n});\n```\n\n#### sh.rm(path, [options], callback)\u003ca name=\"rm\"\u003e\u003c/a\u003e\n\nRemoves (deletes) the file or directory at `path`. If `path` is a file, it will\nbe removed. If `path` is a directory, it will be removed if it is empty, otherwise\nthe callback will receive an error. In order to remove non-empty directories,\nuse the `recursive=true` option.\n\nExample:\n\n```javascript\nsh.rm('./file', function(err) {\n  if(err) throw err;\n  // ./file is now removed\n});\n\nsh.rm('/dir', { recursive: true }, function(err) {\n  if(err) throw err;\n  // /dir and all its children are now removed\n});\n```\n\n#### sh.tempDir(callback)\u003ca name=\"tempDir\"\u003e\u003c/a\u003e\n\nGets the path to the shell's temporary directory, creating it if it\ndoes not already exist. The temp directory to use is specified in the\n`env.TMP` environment variable. The callback receives an error\nand the `tempDir` path. NOTE: it is safe to call this many times (i.e.,\nthe temp dir will only be created once). No effort is made to clean-up\nthe temp dir, and it is up to the caller to destroy it if desired.\n\nExample:\n\n```javascript\n// Default /tmp dir\nsh.tempDir(function(err, tmp) {\n  if(err) throw err;\n  // tmp is now '/tmp' by default, and /tmp exists\n});\n\n// Specify a tmp dir path\nsh.env.TMP = '/temporary'\nsh.tempDir(function(err, tmp) {\n  if(err) throw err;\n  // tmp is now '/temporary', and /temporary exists\n});\n```\n\n#### sh.mkdirp(path, callback)\u003ca name=\"mkdirp\"\u003e\u003c/a\u003e\n\nRecursively creates the directory at the provided path. If the\ndirectory already exists, no error is returned. All parents must\nbe valid directories (not files).\n\nExample:\n\n```javascript\n// Default empty filesystem\nsh.mkdirp('/test/mkdirp', function(err) {\n  if(err) throw err;\n  // the root '/' now contains a directory 'test' containing the directory 'mkdirp'\n});\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffilerjs%2Ffiler","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffilerjs%2Ffiler","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffilerjs%2Ffiler/lists"}