CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-ssh2-sftp-client

Promise-based SFTP client for Node.js that wraps the ssh2 module

Pending
Overview
Eval results
Files

directory-operations.mddocs/

Directory Operations

Directory management functionality including listing, creation, deletion, and bulk transfer operations with filtering and concurrent processing support.

Capabilities

List Directory

Lists the contents of a remote directory with optional filtering.

/**
 * List contents of a remote directory
 * @param remotePath - Path to remote directory
 * @param filter - Optional filter function to select entries
 * @param addListeners - Whether to add event listeners (default: true)
 * @returns Promise resolving to array of file entry objects
 */
list(remotePath, filter, addListeners = true): Promise<Array>;

Usage Examples:

// List all files and directories
const files = await sftp.list('/remote/directory');
console.log(files);

// List with filter function
const textFiles = await sftp.list('/remote/docs', (item) => {
  return item.name.endsWith('.txt');
});

// List only directories
const directories = await sftp.list('/remote/path', (item) => {
  return item.type === 'd';
});

// List files larger than 1MB
const largeFiles = await sftp.list('/remote/files', (item) => {
  return item.type === '-' && item.size > 1024 * 1024;
});

File Entry Object:

interface FileEntry {
  type: string;           // 'd' for directory, '-' for file, 'l' for link
  name: string;           // File/directory name
  size: number;           // Size in bytes
  modifyTime: number;     // Last modified time (milliseconds)
  accessTime: number;     // Last access time (milliseconds)
  rights: {
    user: string;         // User permissions (rwx format)
    group: string;        // Group permissions (rwx format)
    other: string;        // Other permissions (rwx format)
  };
  owner: number;          // Owner UID
  group: number;          // Group GID
  longname: string;       // Full listing format string
}

Make Directory

Creates directories on the remote server with optional recursive creation.

/**
 * Create directory on remote server
 * @param remotePath - Path for new directory
 * @param recursive - Create parent directories if needed (default: false)
 * @returns Promise resolving to success message
 */
mkdir(remotePath, recursive = false): Promise<String>;

Usage Examples:

// Create single directory
await sftp.mkdir('/remote/new-folder');

// Create directory tree recursively
await sftp.mkdir('/remote/path/to/deep/folder', true);

// Create directory with error handling
try {
  await sftp.mkdir('/remote/existing-folder');
} catch (err) {
  if (err.code !== 'EEXIST') {
    throw err; // Re-throw if not "already exists" error
  }
}

Remove Directory

Removes directories from the remote server with optional recursive deletion.

/**
 * Remove directory from remote server
 * @param remoteDir - Path to directory to remove
 * @param recursive - Remove contents recursively (default: false)
 * @returns Promise resolving to success message
 */
rmdir(remoteDir, recursive = false): Promise<String>;

Usage Examples:

// Remove empty directory
await sftp.rmdir('/remote/empty-folder');

// Remove directory and all contents
await sftp.rmdir('/remote/folder-with-files', true);

// Safe removal with existence check
const exists = await sftp.exists('/remote/maybe-folder');
if (exists === 'd') {
  await sftp.rmdir('/remote/maybe-folder', true);
}

Upload Directory

Recursively uploads a local directory to the remote server with filtering and performance options.

/**
 * Upload local directory to remote server recursively
 * @param srcDir - Local source directory path
 * @param dstDir - Remote destination directory path
 * @param options - Optional upload configuration
 * @returns Promise resolving to success message
 */
uploadDir(srcDir, dstDir, options): Promise<String>;

Upload Options:

interface UploadDirectoryOptions {
  filter?: (filePath: string, isDirectory: boolean) => boolean;
  useFastput?: boolean;   // Use fastPut for file uploads (default: false)
}

Usage Examples:

// Upload entire directory
await sftp.uploadDir('/local/project', '/remote/project');

// Upload with filtering
await sftp.uploadDir('/local/source', '/remote/source', {
  filter: (filePath, isDirectory) => {
    // Skip hidden files and node_modules
    const name = path.basename(filePath);
    return !name.startsWith('.') && name !== 'node_modules';
  }
});

// Upload with fast transfers
await sftp.uploadDir('/local/data', '/remote/data', {
  useFastput: true,
  filter: (filePath, isDirectory) => {
    // Only upload .txt and .json files
    return isDirectory || filePath.match(/\.(txt|json)$/);
  }
});

Download Directory

Recursively downloads a remote directory to the local system with filtering and performance options.

/**
 * Download remote directory to local system recursively
 * @param srcDir - Remote source directory path
 * @param dstDir - Local destination directory path
 * @param options - Optional download configuration
 * @returns Promise resolving to success message
 */
downloadDir(srcDir, dstDir, options = { filter: null, useFastget: false }): Promise<String>;

Download Options:

interface DownloadDirectoryOptions {
  filter?: (filePath: string, isDirectory: boolean) => boolean;
  useFastget?: boolean;   // Use fastGet for file downloads (default: false)
}

Usage Examples:

// Download entire directory
await sftp.downloadDir('/remote/backup', '/local/backup');

// Download with filtering
await sftp.downloadDir('/remote/logs', '/local/logs', {
  filter: (filePath, isDirectory) => {
    // Only download .log files from today
    if (isDirectory) return true;
    const today = new Date().toISOString().split('T')[0];
    return filePath.includes(today) && filePath.endsWith('.log');
  }
});

// Download with fast transfers
await sftp.downloadDir('/remote/media', '/local/media', {
  useFastget: true,
  filter: (filePath, isDirectory) => {
    // Download images and videos only
    return isDirectory || filePath.match(/\.(jpg|png|mp4|avi)$/i);
  }
});

Bulk Operation Features

Concurrent Processing

Directory operations use concurrent processing with configurable limits:

  • Promise Limit: Control maximum concurrent operations (default: 10)
  • Batch Processing: Operations are grouped into batches for efficiency
  • Progress Events: Upload/download operations emit progress events

Event Monitoring

Monitor bulk operations with custom event handlers:

// Listen for upload progress
sftp.client.on('upload', (info) => {
  console.log(`Uploading: ${info.source} -> ${info.destination}`);
});

// Listen for download progress
sftp.client.on('download', (info) => {
  console.log(`Downloading: ${info.source} -> ${info.destination}`);
});

Filtering Strategies

Common filtering patterns for directory operations:

// File extension filter
const imageFilter = (filePath, isDirectory) => {
  return isDirectory || /\.(jpg|jpeg|png|gif)$/i.test(filePath);
};

// Size-based filter
const smallFilesFilter = (filePath, isDirectory) => {
  if (isDirectory) return true;
  const stats = fs.statSync(filePath);
  return stats.size < 10 * 1024 * 1024; // Less than 10MB
};

// Date-based filter
const recentFilter = (filePath, isDirectory) => {
  if (isDirectory) return true;
  const stats = fs.statSync(filePath);
  const weekAgo = Date.now() - (7 * 24 * 60 * 60 * 1000);
  return stats.mtime.getTime() > weekAgo;
};

// Complex filter combining multiple criteria
const complexFilter = (filePath, isDirectory) => {
  if (isDirectory) {
    // Skip hidden and system directories
    const dirName = path.basename(filePath);
    return !dirName.startsWith('.') && dirName !== 'node_modules';
  }
  
  // For files: only .js/.json files, not too large
  const ext = path.extname(filePath).toLowerCase();
  if (!['.js', '.json'].includes(ext)) return false;
  
  const stats = fs.statSync(filePath);
  return stats.size < 5 * 1024 * 1024; // Less than 5MB
};

Performance Optimization

  • Use filtering to reduce unnecessary transfers
  • Enable fast transfers for large files when server supports it
  • Adjust promise limits based on server capabilities and network conditions
  • Monitor progress events to track bulk operation status
  • Handle errors gracefully to avoid partial transfers

Error Handling

Directory operation errors provide detailed context:

  • ERR_BAD_PATH: Invalid directory path or permissions
  • ENOENT: Directory does not exist
  • ENOTDIR: Path exists but is not a directory
  • EEXIST: Directory already exists (mkdir)
  • ENOTEMPTY: Directory not empty (rmdir without recursive)
  • Local file system errors during directory transfers

Install with Tessl CLI

npx tessl i tessl/npm-ssh2-sftp-client

docs

connection-management.md

directory-operations.md

file-management.md

file-operations.md

filesystem-info.md

index.md

stream-operations.md

tile.json