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

filesystem-info.mddocs/

File System Information

File and directory information retrieval including existence checking, attribute inspection, path resolution, and working directory management.

Capabilities

Check Existence

Tests whether a remote file or directory exists and returns its type.

/**
 * Test if remote object exists and return its type
 * @param remotePath - Path to remote object
 * @returns Promise resolving to type string or false
 *          'd' = directory, '-' = file, 'l' = symbolic link, false = does not exist
 */
exists(remotePath): Promise<Boolean|String>;

Usage Examples:

// Check if file exists
const fileExists = await sftp.exists('/remote/file.txt');
if (fileExists === '-') {
  console.log('File exists');
} else if (fileExists === false) {
  console.log('File does not exist');
}

// Check if directory exists
const dirExists = await sftp.exists('/remote/folder');
if (dirExists === 'd') {
  console.log('Directory exists');
}

// Check for symbolic link
const linkExists = await sftp.exists('/remote/symlink');
if (linkExists === 'l') {
  console.log('Symbolic link exists');
}

// Conditional operations based on existence
const target = '/remote/config.json';
const exists = await sftp.exists(target);
if (exists === '-') {
  // File exists, download it
  await sftp.get(target, '/local/config.json');
} else if (exists === false) {
  // File doesn't exist, create default
  await sftp.put('/local/default-config.json', target);
}

Get File Statistics

Retrieves detailed attributes for a remote file or directory, following symbolic links.

/**
 * Get file/directory attributes (follows symbolic links)
 * @param remotePath - Path to remote object
 * @returns Promise resolving to file statistics object
 */
stat(remotePath): Promise<Object>;

Usage Examples:

// Get file statistics
const stats = await sftp.stat('/remote/file.txt');
console.log(`Size: ${stats.size} bytes`);
console.log(`Modified: ${new Date(stats.modifyTime)}`);
console.log(`Is file: ${stats.isFile}`);
console.log(`Permissions: ${stats.mode.toString(8)}`);

// Check if path is directory
const dirStats = await sftp.stat('/remote/folder');
if (dirStats.isDirectory) {
  console.log('Path is a directory');
}

// File size comparison
const fileStats = await sftp.stat('/remote/large-file.dat');
if (fileStats.size > 100 * 1024 * 1024) {
  console.log('File is larger than 100MB, using fastGet');
  await sftp.fastGet('/remote/large-file.dat', '/local/large-file.dat');
}

Get Link Statistics

Retrieves detailed attributes for a remote file or directory, NOT following symbolic links.

/**
 * Get file/directory attributes (does not follow symbolic links)
 * @param remotePath - Path to remote object
 * @returns Promise resolving to file statistics object
 */
lstat(remotePath): Promise<Object>;

Usage Examples:

// Get symbolic link info (not target info)
const linkStats = await sftp.lstat('/remote/symlink');
if (linkStats.isSymbolicLink) {
  console.log('This is a symbolic link');
  // Get target info separately if needed
  const targetStats = await sftp.stat('/remote/symlink');
  console.log(`Link points to ${targetStats.isFile ? 'file' : 'directory'}`);
}

// Compare link vs target attributes
const linkInfo = await sftp.lstat('/remote/link-to-file');
const targetInfo = await sftp.stat('/remote/link-to-file');
console.log(`Link size: ${linkInfo.size}, Target size: ${targetInfo.size}`);

Resolve Real Path

Returns the absolute path on the remote server, resolving relative paths and symbolic links.

/**
 * Get absolute path on remote server, resolving . and .. components
 * @param remotePath - Path to resolve (can be relative)
 * @param addListeners - Whether to add event listeners (default: true)
 * @returns Promise resolving to absolute path string or empty string if not found
 */
realPath(remotePath, addListeners = true): Promise<String>;

Usage Examples:

// Resolve relative path
const absolutePath = await sftp.realPath('../documents/file.txt');
console.log(`Absolute path: ${absolutePath}`);

// Resolve current directory
const currentDir = await sftp.realPath('.');
console.log(`Current directory: ${currentDir}`);

// Resolve symbolic link to actual path
const realPath = await sftp.realPath('/remote/symlink-to-file');
if (realPath) {
  console.log(`Link resolves to: ${realPath}`);
} else {
  console.log('Path does not exist');
}

// Path validation
const userInput = '../../../etc/passwd';
const resolved = await sftp.realPath(userInput);
if (resolved.startsWith('/home/user/')) {
  console.log('Path is within allowed directory');
} else {
  console.log('Path is outside allowed directory');
}

Get Current Working Directory

Returns the current working directory path on the remote server.

/**
 * Get current working directory path
 * @returns Promise resolving to current directory path
 */
cwd(): Promise<String>;

Usage Examples:

// Get current directory
const currentDir = await sftp.cwd();
console.log(`Working directory: ${currentDir}`);

// Store current directory before changing
const originalDir = await sftp.cwd();
// ... perform operations in different directories ...
// Note: SFTP doesn't have a built-in cd command, 
// but you can use absolute paths or realPath for navigation

// Build relative paths from current directory
const workingDir = await sftp.cwd();
const configFile = `${workingDir}/config/app.json`;
const exists = await sftp.exists(configFile);

File Statistics Object

interface FileStats {
  mode: number;           // File mode/permissions
  uid: number;            // Owner user ID
  gid: number;            // Owner group ID
  size: number;           // Size in bytes
  accessTime: number;     // Last access time (milliseconds since epoch)
  modifyTime: number;     // Last modify time (milliseconds since epoch)
  isDirectory: boolean;   // True if directory
  isFile: boolean;        // True if regular file
  isBlockDevice: boolean; // True if block device
  isCharacterDevice: boolean; // True if character device
  isSymbolicLink: boolean; // True if symbolic link
  isFIFO: boolean;        // True if FIFO/named pipe
  isSocket: boolean;      // True if socket
}

Common Usage Patterns

Safe File Operations

// Check before download
const remoteFile = '/remote/data.json';
const exists = await sftp.exists(remoteFile);
if (exists === '-') {
  const stats = await sftp.stat(remoteFile);
  if (stats.size > 0) {
    await sftp.get(remoteFile, '/local/data.json');
  } else {
    console.log('Remote file is empty');
  }
} else {
  console.log('Remote file does not exist');
}

Directory Traversal

// Navigate and inspect directories
const currentDir = await sftp.cwd();
console.log(`Starting in: ${currentDir}`);

const targetDir = './subdirectory';
const absoluteTarget = await sftp.realPath(targetDir);
if (absoluteTarget) {
  const stats = await sftp.stat(absoluteTarget);
  if (stats.isDirectory) {
    const files = await sftp.list(absoluteTarget);
    console.log(`Directory contains ${files.length} items`);
  }
}

File Size and Date Filtering

// Find large files modified recently
const files = await sftp.list('/remote/data');
const largeFreshFiles = [];

for (const file of files) {
  if (file.type === '-') { // Regular file
    const stats = await sftp.stat(`/remote/data/${file.name}`);
    const dayOld = Date.now() - (24 * 60 * 60 * 1000);
    const sizeMB = stats.size / (1024 * 1024);
    
    if (stats.modifyTime > dayOld && sizeMB > 10) {
      largeFreshFiles.push({
        name: file.name,
        size: sizeMB,
        modified: new Date(stats.modifyTime)
      });
    }
  }
}

Permission Checking

// Check file permissions
const stats = await sftp.stat('/remote/script.sh');
const permissions = stats.mode & parseInt('777', 8);
const isExecutable = (permissions & parseInt('111', 8)) !== 0;

console.log(`Permissions: ${permissions.toString(8)}`);
console.log(`Executable: ${isExecutable}`);

Error Handling

File system information errors provide specific context:

  • ENOENT: File or directory does not exist
  • EACCES: Permission denied for stat operation
  • ERR_BAD_PATH: Invalid path format
  • ERR_NOT_CONNECTED: No active SFTP connection
  • Network errors during remote file system access

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