阿里云主机折上折
  • 微信号
Current Site:Index > Directory operations

Directory operations

Author:Chuan Chen 阅读数:62237人阅读 分类: Node.js

File System Basics

Node.js provides the fs module for handling file system operations. This module includes both synchronous and asynchronous methods, with asynchronous methods generally being preferred as they do not block the event loop. To use the fs module, you first need to require it:

const fs = require('fs');
const fsPromises = require('fs').promises; // Promise version

Creating Directories

Creating directories is one of the most basic tasks in directory operations. Node.js provides the mkdir() and mkdirSync() methods to achieve this.

// Asynchronously create a directory
fs.mkdir('new-directory', (err) => {
  if (err) throw err;
  console.log('Directory created successfully');
});

// Synchronously create a directory
try {
  fs.mkdirSync('new-directory-sync');
  console.log('Directory created successfully (synchronous)');
} catch (err) {
  console.error(err);
}

// Create a directory using Promises
async function createDir() {
  try {
    await fsPromises.mkdir('new-directory-promise');
    console.log('Directory created successfully (Promise)');
  } catch (err) {
    console.error(err);
  }
}
createDir();

Recursively Creating Directories

Sometimes you need to create a nested directory structure. You can use the recursive option:

// Recursively create directories
fs.mkdir('parent/child/grandchild', { recursive: true }, (err) => {
  if (err) throw err;
  console.log('Recursive directories created successfully');
});

Reading Directory Contents

Reading directory contents is a common operation, achievable with the readdir() method:

// Asynchronously read a directory
fs.readdir('./', (err, files) => {
  if (err) throw err;
  console.log('Directory contents:', files);
});

// Synchronously read a directory
try {
  const files = fs.readdirSync('./');
  console.log('Directory contents (synchronous):', files);
} catch (err) {
  console.error(err);
}

// Read a directory using Promises
async function readDir() {
  try {
    const files = await fsPromises.readdir('./');
    console.log('Directory contents (Promise):', files);
  } catch (err) {
    console.error(err);
  }
}
readDir();

Getting Directory Details

Sometimes you need to get detailed information about a directory, such as creation time or modification time:

// Get directory status
fs.stat('some-directory', (err, stats) => {
  if (err) throw err;
  console.log('Is directory:', stats.isDirectory());
  console.log('Creation time:', stats.birthtime);
  console.log('Modification time:', stats.mtime);
});

Renaming Directories

To rename a directory, use the rename() method:

// Rename a directory
fs.rename('old-name', 'new-name', (err) => {
  if (err) throw err;
  console.log('Directory renamed successfully');
});

Deleting Directories

There are several methods for deleting directories, depending on whether the directory is empty:

// Delete an empty directory
fs.rmdir('empty-directory', (err) => {
  if (err) throw err;
  console.log('Empty directory deleted successfully');
});

// Recursively delete a non-empty directory
fs.rm('non-empty-directory', { recursive: true }, (err) => {
  if (err) throw err;
  console.log('Non-empty directory deleted successfully');
});

Practical Directory Operation Tips

Checking if a Directory Exists

function directoryExists(path) {
  try {
    return fs.statSync(path).isDirectory();
  } catch (err) {
    return false;
  }
}

Traversing a Directory Tree

function walkDir(dir, callback) {
  fs.readdirSync(dir).forEach(f => {
    let dirPath = path.join(dir, f);
    let isDirectory = fs.statSync(dirPath).isDirectory();
    isDirectory ? walkDir(dirPath, callback) : callback(path.join(dir, f));
  });
}

walkDir('./', file => console.log(file));

Creating a Temporary Directory

const os = require('os');
const path = require('path');

const tempDir = path.join(os.tmpdir(), 'my-temp-dir');
fs.mkdirSync(tempDir);

Error Handling in Directory Operations

Proper error handling is crucial in directory operations:

fs.readdir('/nonexistent', (err, files) => {
  if (err) {
    if (err.code === 'ENOENT') {
      console.error('Directory does not exist');
    } else {
      console.error('Unknown error occurred:', err);
    }
    return;
  }
  console.log(files);
});

Performance Considerations

When dealing with a large number of directory operations, performance becomes a key factor:

  1. Synchronous methods block the event loop and should be avoided in performance-critical applications.
  2. For batch operations, consider using streams or worker queues.
  3. For frequently accessed directories, you can cache the directory contents.
// Using a worker queue for heavy directory operations
const { Worker, isMainThread, workerData } = require('worker_threads');

if (isMainThread) {
  const worker = new Worker(__filename, {
    workerData: { dir: './large-directory' }
  });
} else {
  processDir(workerData.dir);
}

function processDir(dir) {
  // Handle heavy directory tasks
}

Cross-Platform Considerations

Different operating systems handle directories differently:

  1. Windows uses backslashes () as path separators, while Unix uses forward slashes (/).
  2. Path case sensitivity varies across systems.
  3. Use the path module to handle paths and avoid these issues.
const path = require('path');

// Cross-platform path joining
const fullPath = path.join('dir', 'subdir', 'file.txt');

Advanced Directory Monitoring

Node.js provides the fs.watch() method to monitor directory changes:

// Monitor directory changes
const watcher = fs.watch('./watched-dir', (eventType, filename) => {
  console.log(`Event type: ${eventType}`);
  if (filename) {
    console.log(`Filename: ${filename}`);
  }
});

// Stop monitoring
setTimeout(() => {
  watcher.close();
}, 10000);

Combining Directory Operations with Streams

Combining directory operations with streams can efficiently handle large numbers of files:

const { Readable } = require('stream');

class DirectoryStream extends Readable {
  constructor(dir) {
    super({ objectMode: true });
    this.dir = dir;
    this.files = fs.readdirSync(dir);
    this.index = 0;
  }
  
  _read() {
    if (this.index < this.files.length) {
      this.push(path.join(this.dir, this.files[this.index++]));
    } else {
      this.push(null);
    }
  }
}

const dirStream = new DirectoryStream('./large-dir');
dirStream.on('data', file => console.log(file));

本站部分内容来自互联网,一切版权均归源网站或源作者所有。

如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn

Front End Chuan

Front End Chuan, Chen Chuan's Code Teahouse 🍵, specializing in exorcising all kinds of stubborn bugs 💻. Daily serving baldness-warning-level development insights 🛠️, with a bonus of one-liners that'll make you laugh for ten years 🐟. Occasionally drops pixel-perfect romance brewed in a coffee cup ☕.