Skip to content

Files and System: fs / path / process ​

fs, path, and process are global objects styled after Node.js — no import needed. Every fs API comes in both a synchronous (xxxSync) and a callback-based async flavor:

js
// Synchronous style
fs.writeFileSync("hello.txt", "hello gox")
console.log(fs.readFileSync("hello.txt", "utf-8"))    // → hello gox
fs.appendFileSync("hello.txt", "!")
console.log(fs.existsSync("hello.txt"))               // → true

let st = fs.statSync("hello.txt")
console.log(st.size, st.isFile(), st.isDirectory())   // 10 true false

for (const f of fs.readdirSync(".")) console.log(f)
fs.mkdirSync("logs", { recursive: true })

// Callback-based async (error-first, Node semantics)
fs.readFile("hello.txt", "utf-8", (err, data) => {
  if (err) throw err
  console.log(data)
})

// Promise-based await also works
const text = await fs.readFile("hello.txt", "utf-8")
ModuleCommon APIs
fsreadFileSync/readFile, writeFileSync/writeFile, appendFileSync, readBytesSync (returns a byte array), existsSync, statSync/stat, readdirSync/readdir, mkdirSync/mkdir, renameSync, copyFileSync, rmSync, unlinkSync/unlink, rmdirSync
pathjoin, basename, dirname, extname, resolve, isAbsolute, sep, delimiter
processargv (command-line arguments), env (environment variables), cwd(), chdir(), exit(code), platform (windows/linux/darwin), pid
js
let cfgPath = path.join(process.cwd(), "app.json")
console.log(path.extname("archive.tar.gz"))     // → .gz
console.log(process.platform, process.pid)
console.log(process.argv)                       // [gox, app.js, ...]

Two easy-to-miss details

Encoding parameter: fs.readFileSync(path) returns a UTF-8 string by default; pass 'base64' to get base64 encoding; use fs.readBytesSync(path) for raw bytes.
Path base: relative paths in fs are resolved against the process working directory, not "the script's directory". A script may come from stdin / a string / a packed artifact and has no "containing directory" concept at all.