or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

advanced-features.mdcode-execution.mdffi.mdfile-system.mdindex.mdinteroperability.mdio-streams.mdpackage-management.mdruntime-loading.md

file-system.mddocs/

0

# File System

1

2

Access and manipulate the Emscripten virtual file system with support for mounting host directories and browser file systems.

3

4

## File System API

5

6

### FS

7

8

Complete Emscripten file system interface for file and directory operations.

9

10

```javascript { .api }

11

const FS: {

12

// File operations

13

readFile(path: string, options?: { encoding?: string }): string | Uint8Array;

14

writeFile(path: string, data: string | ArrayBufferView, options?: { encoding?: string }): void;

15

unlink(path: string): void;

16

rename(oldPath: string, newPath: string): void;

17

18

// Directory operations

19

mkdir(path: string, mode?: number): void;

20

rmdir(path: string): void;

21

readdir(path: string): string[];

22

23

// File information

24

stat(path: string): FSStats;

25

lstat(path: string): FSStats;

26

exists(path: string): boolean;

27

28

// File system mounting

29

mount(type: any, options: any, mountpoint: string): void;

30

unmount(mountpoint: string): void;

31

32

// Additional utilities

33

mkdirTree(path: string): void;

34

lookupPath(path: string, options?: any): { path: string; node: any };

35

isFile(mode: number): boolean;

36

isDir(mode: number): boolean;

37

isLink(mode: number): boolean;

38

isChrdev(mode: number): boolean;

39

isBlkdev(mode: number): boolean;

40

isFIFO(mode: number): boolean;

41

isSocket(mode: number): boolean;

42

43

// File systems

44

filesystems: {

45

MEMFS: any;

46

IDBFS: any;

47

NODEFS: any;

48

PROXYFS: any;

49

WORKERFS: any;

50

NATIVEFS_ASYNC: any;

51

};

52

};

53

```

54

55

### PATH

56

57

Path manipulation utilities similar to Node.js path module.

58

59

```javascript { .api }

60

const PATH: {

61

dirname(path: string): string;

62

basename(path: string, ext?: string): string;

63

extname(path: string): string;

64

join(...paths: string[]): string;

65

resolve(...paths: string[]): string;

66

normalize(path: string): string;

67

isAbsolute(path: string): boolean;

68

relative(from: string, to: string): string;

69

sep: string;

70

delimiter: string;

71

};

72

```

73

74

## Mounting External File Systems

75

76

### mountNodeFS

77

78

Mount a host directory into the virtual file system (Node.js only).

79

80

```javascript { .api }

81

function mountNodeFS(emscriptenPath: string, hostPath: string): void;

82

```

83

84

**Parameters:**

85

- `emscriptenPath` - Virtual file system mount point (must be absolute)

86

- `hostPath` - Host directory path to mount

87

88

### mountNativeFS

89

90

Mount a browser FileSystemDirectoryHandle into the virtual file system.

91

92

```javascript { .api }

93

function mountNativeFS(

94

path: string,

95

fileSystemHandle: FileSystemDirectoryHandle

96

): Promise<NativeFS>;

97

```

98

99

**Parameters:**

100

- `path` - Virtual file system mount point (must be absolute)

101

- `fileSystemHandle` - Browser FileSystemDirectoryHandle

102

103

**Returns:** Promise resolving to NativeFS object with sync capabilities

104

105

## Usage Examples

106

107

### Basic File Operations

108

109

```javascript

110

// Create directories

111

pyodide.FS.mkdir("/workspace");

112

pyodide.FS.mkdir("/data");

113

114

// Write files

115

pyodide.FS.writeFile("/workspace/config.py", `

116

DEBUG = True

117

DATABASE_URL = "sqlite:///app.db"

118

SECRET_KEY = "development-key"

119

`);

120

121

pyodide.FS.writeFile("/data/sample.txt", "Hello from Pyodide file system!");

122

123

// Read files

124

const configContent = pyodide.FS.readFile("/workspace/config.py", { encoding: "utf8" });

125

console.log("Config file:", configContent);

126

127

const binaryData = pyodide.FS.readFile("/data/sample.txt"); // Returns Uint8Array

128

const textData = pyodide.FS.readFile("/data/sample.txt", { encoding: "utf8" });

129

console.log("Text data:", textData);

130

```

131

132

### Directory Operations

133

134

```javascript

135

// Create nested directories

136

pyodide.FS.mkdirTree("/project/src/utils");

137

138

// List directory contents

139

const files = pyodide.FS.readdir("/workspace");

140

console.log("Workspace files:", files);

141

142

// Check if path exists

143

if (pyodide.FS.exists("/workspace/config.py")) {

144

console.log("Config file exists");

145

}

146

147

// Get file information

148

const stats = pyodide.FS.stat("/workspace/config.py");

149

console.log("File size:", stats.size);

150

console.log("Modified:", new Date(stats.mtime));

151

console.log("Is file:", pyodide.FS.isFile(stats.mode));

152

console.log("Is directory:", pyodide.FS.isDir(stats.mode));

153

```

154

155

### Path Manipulation

156

157

```javascript

158

// Join paths

159

const configPath = pyodide.PATH.join("/workspace", "config.py");

160

console.log("Config path:", configPath); // /workspace/config.py

161

162

// Get directory and filename

163

console.log("Directory:", pyodide.PATH.dirname(configPath)); // /workspace

164

console.log("Filename:", pyodide.PATH.basename(configPath)); // config.py

165

console.log("Extension:", pyodide.PATH.extname(configPath)); // .py

166

167

// Normalize paths

168

const messyPath = "/workspace/../workspace/./config.py";

169

console.log("Normalized:", pyodide.PATH.normalize(messyPath)); // /workspace/config.py

170

171

// Check if absolute

172

console.log("Is absolute:", pyodide.PATH.isAbsolute("/workspace")); // true

173

console.log("Is absolute:", pyodide.PATH.isAbsolute("config.py")); // false

174

```

175

176

### Working with Python Files

177

178

```javascript

179

// Create Python module

180

pyodide.FS.writeFile("/workspace/mymodule.py", `

181

def calculate(x, y):

182

return x ** 2 + y ** 2

183

184

def greet(name):

185

return f"Hello, {name}!"

186

187

PI = 3.14159

188

`);

189

190

// Use the module in Python

191

pyodide.runPython(`

192

import sys

193

sys.path.append("/workspace")

194

195

import mymodule

196

197

result = mymodule.calculate(3, 4)

198

greeting = mymodule.greet("Pyodide")

199

200

print(f"Calculation result: {result}")

201

print(greeting)

202

print(f"PI value: {mymodule.PI}")

203

`);

204

```

205

206

### Node.js Host Directory Mounting

207

208

```javascript

209

// Mount host directory (Node.js only)

210

try {

211

pyodide.mountNodeFS("/host", "/path/to/host/directory");

212

213

// Access host files from Python

214

pyodide.runPython(`

215

with open("/host/data.txt", "r") as f:

216

content = f.read()

217

print("Host file content:", content)

218

219

# Write to host directory

220

with open("/host/output.txt", "w") as f:

221

f.write("Generated by Pyodide")

222

`);

223

224

console.log("Host directory mounted successfully");

225

} catch (error) {

226

console.error("Failed to mount host directory:", error.message);

227

}

228

```

229

230

### Browser File System Access

231

232

```javascript

233

// Request directory access (browser only)

234

async function setupWorkspaceAccess() {

235

try {

236

// Request directory picker

237

const dirHandle = await window.showDirectoryPicker();

238

239

// Mount the directory

240

const nativeFS = await pyodide.mountNativeFS("/workspace", dirHandle);

241

242

// Access files from the selected directory

243

pyodide.runPython(`

244

import os

245

files = os.listdir("/workspace")

246

print("Available files:", files)

247

248

# Read existing file if available

249

if "data.csv" in files:

250

import pandas as pd

251

df = pd.read_csv("/workspace/data.csv")

252

print("Data shape:", df.shape)

253

254

# Create new file

255

with open("/workspace/pyodide_output.txt", "w") as f:

256

f.write("Created by Pyodide in browser")

257

`);

258

259

// Sync changes back to native file system

260

await nativeFS.syncfs();

261

console.log("Files synced to native file system");

262

263

} catch (error) {

264

console.error("File system access denied:", error);

265

}

266

}

267

```

268

269

### Persistent Storage with IDBFS

270

271

```javascript

272

// Mount IndexedDB file system for persistence (browser only)

273

pyodide.FS.mkdir("/persistent");

274

pyodide.FS.mount(pyodide.FS.filesystems.IDBFS, {}, "/persistent");

275

276

// Sync from IndexedDB

277

pyodide.FS.syncfs(true, (err) => {

278

if (err) {

279

console.error("Failed to sync from IndexedDB:", err);

280

return;

281

}

282

283

// Work with persistent files

284

pyodide.runPython(`

285

import os

286

persistent_file = "/persistent/user_data.json"

287

288

if os.path.exists(persistent_file):

289

import json

290

with open(persistent_file, "r") as f:

291

data = json.load(f)

292

print("Loaded persistent data:", data)

293

else:

294

# Create initial data

295

import json

296

data = {"visits": 1, "last_visit": "2024-01-01"}

297

with open(persistent_file, "w") as f:

298

json.dump(data, f)

299

print("Created initial persistent data")

300

`);

301

302

// Sync to IndexedDB

303

pyodide.FS.syncfs(false, (err) => {

304

if (err) {

305

console.error("Failed to sync to IndexedDB:", err);

306

} else {

307

console.log("Data persisted to IndexedDB");

308

}

309

});

310

});

311

```

312

313

### File Streaming and Large Files

314

315

```javascript

316

// Handle large files efficiently

317

function writeFileInChunks(path, data, chunkSize = 1024 * 1024) {

318

const encoder = new TextEncoder();

319

const bytes = encoder.encode(data);

320

321

// Open file for writing

322

const fd = pyodide.FS.open(path, "w");

323

324

try {

325

let offset = 0;

326

while (offset < bytes.length) {

327

const chunk = bytes.slice(offset, offset + chunkSize);

328

pyodide.FS.write(fd, chunk, 0, chunk.length);

329

offset += chunkSize;

330

}

331

} finally {

332

pyodide.FS.close(fd);

333

}

334

}

335

336

// Create large file

337

const largeContent = "x".repeat(10 * 1024 * 1024); // 10MB

338

writeFileInChunks("/data/large_file.txt", largeContent);

339

340

// Read file in chunks

341

function readFileInChunks(path, chunkSize = 1024 * 1024) {

342

const stats = pyodide.FS.stat(path);

343

const fd = pyodide.FS.open(path, "r");

344

const chunks = [];

345

346

try {

347

let bytesRead = 0;

348

while (bytesRead < stats.size) {

349

const buffer = new Uint8Array(Math.min(chunkSize, stats.size - bytesRead));

350

const read = pyodide.FS.read(fd, buffer, 0, buffer.length);

351

chunks.push(buffer.slice(0, read));

352

bytesRead += read;

353

}

354

} finally {

355

pyodide.FS.close(fd);

356

}

357

358

// Combine chunks

359

const totalLength = chunks.reduce((sum, chunk) => sum + chunk.length, 0);

360

const result = new Uint8Array(totalLength);

361

let offset = 0;

362

for (const chunk of chunks) {

363

result.set(chunk, offset);

364

offset += chunk.length;

365

}

366

367

return result;

368

}

369

```

370

371

### File System Utilities

372

373

```javascript

374

// Recursive directory listing

375

function listFilesRecursive(dirPath) {

376

const result = [];

377

378

function traverse(currentPath) {

379

const items = pyodide.FS.readdir(currentPath);

380

381

for (const item of items) {

382

if (item === "." || item === "..") continue;

383

384

const fullPath = pyodide.PATH.join(currentPath, item);

385

const stats = pyodide.FS.stat(fullPath);

386

387

if (pyodide.FS.isDir(stats.mode)) {

388

result.push({ path: fullPath, type: "directory" });

389

traverse(fullPath);

390

} else {

391

result.push({

392

path: fullPath,

393

type: "file",

394

size: stats.size,

395

modified: new Date(stats.mtime)

396

});

397

}

398

}

399

}

400

401

traverse(dirPath);

402

return result;

403

}

404

405

// Copy file with progress

406

function copyFileWithProgress(src, dst, progressCallback) {

407

const stats = pyodide.FS.stat(src);

408

const srcFd = pyodide.FS.open(src, "r");

409

const dstFd = pyodide.FS.open(dst, "w");

410

411

try {

412

const chunkSize = 64 * 1024; // 64KB chunks

413

let bytesCopied = 0;

414

415

while (bytesCopied < stats.size) {

416

const remaining = stats.size - bytesCopied;

417

const currentChunkSize = Math.min(chunkSize, remaining);

418

const buffer = new Uint8Array(currentChunkSize);

419

420

pyodide.FS.read(srcFd, buffer, 0, currentChunkSize);

421

pyodide.FS.write(dstFd, buffer, 0, currentChunkSize);

422

423

bytesCopied += currentChunkSize;

424

progressCallback?.(bytesCopied, stats.size);

425

}

426

} finally {

427

pyodide.FS.close(srcFd);

428

pyodide.FS.close(dstFd);

429

}

430

}

431

432

// Usage

433

copyFileWithProgress("/data/large_file.txt", "/backup/large_file.txt",

434

(copied, total) => {

435

const percent = (copied / total * 100).toFixed(1);

436

console.log(`Copy progress: ${percent}%`);

437

}

438

);

439

```

440

441

## File System Types

442

443

```javascript { .api }

444

interface FSStats {

445

dev: number;

446

ino: number;

447

mode: number;

448

nlink: number;

449

uid: number;

450

gid: number;

451

rdev: number;

452

size: number;

453

atime: Date;

454

mtime: Date;

455

ctime: Date;

456

blksize: number;

457

blocks: number;

458

}

459

460

interface NativeFS {

461

syncfs(): Promise<void>;

462

}

463

```