0
# File Management
1
2
File management operations including deletion, renaming, permission changes, and remote file copying with advanced features like atomic operations.
3
4
## Capabilities
5
6
### Delete File
7
8
Deletes a file from the remote server with optional error suppression for missing files.
9
10
```javascript { .api }
11
/**
12
* Delete a file on the remote SFTP server
13
* @param remotePath - Path to file to delete
14
* @param notFoundOK - If true, ignore "file not found" errors (default: false)
15
* @param addListeners - Whether to add event listeners (default: true)
16
* @returns Promise resolving to success message
17
*/
18
delete(remotePath, notFoundOK = false, addListeners = true): Promise<String>;
19
```
20
21
**Usage Examples:**
22
23
```javascript
24
// Delete existing file
25
await sftp.delete('/remote/old-file.txt');
26
27
// Delete file, ignore if it doesn't exist
28
await sftp.delete('/remote/maybe-exists.txt', true);
29
30
// Safe deletion with existence check
31
const exists = await sftp.exists('/remote/temp-file.dat');
32
if (exists === '-') {
33
await sftp.delete('/remote/temp-file.dat');
34
console.log('Temporary file deleted');
35
}
36
37
// Bulk deletion with error handling
38
const filesToDelete = ['/remote/file1.txt', '/remote/file2.txt', '/remote/file3.txt'];
39
for (const file of filesToDelete) {
40
try {
41
await sftp.delete(file, true); // Ignore missing files
42
console.log(`Deleted: ${file}`);
43
} catch (err) {
44
console.error(`Failed to delete ${file}: ${err.message}`);
45
}
46
}
47
```
48
49
### Rename File
50
51
Renames or moves a file/directory on the remote server.
52
53
```javascript { .api }
54
/**
55
* Rename a file or directory on the remote server
56
* @param fromPath - Current path of file/directory
57
* @param toPath - New path for file/directory
58
* @param addListeners - Whether to add event listeners (default: true)
59
* @returns Promise resolving to success message
60
*/
61
rename(fromPath, toPath, addListeners = true): Promise<String>;
62
```
63
64
**Usage Examples:**
65
66
```javascript
67
// Simple file rename
68
await sftp.rename('/remote/old-name.txt', '/remote/new-name.txt');
69
70
// Move file to different directory
71
await sftp.rename('/remote/temp/file.dat', '/remote/archive/file.dat');
72
73
// Rename directory
74
await sftp.rename('/remote/old-folder', '/remote/new-folder');
75
76
// Safe rename with existence checks
77
const source = '/remote/source.txt';
78
const destination = '/remote/destination.txt';
79
80
const sourceExists = await sftp.exists(source);
81
const destExists = await sftp.exists(destination);
82
83
if (sourceExists === '-' && destExists === false) {
84
await sftp.rename(source, destination);
85
console.log('File renamed successfully');
86
} else if (destExists !== false) {
87
console.error('Destination already exists');
88
} else {
89
console.error('Source file does not exist');
90
}
91
```
92
93
### POSIX Rename
94
95
Performs atomic rename using the POSIX rename extension (SSH 4.8+).
96
97
```javascript { .api }
98
/**
99
* Rename using POSIX atomic rename extension
100
* @param fromPath - Current path of file/directory
101
* @param toPath - New path for file/directory
102
* @param addListeners - Whether to add event listeners (default: true)
103
* @returns Promise resolving to success message
104
*/
105
posixRename(fromPath, toPath, addListeners = true): Promise<String>;
106
```
107
108
**Important Note**: This method requires SSH server version 4.8 or higher with the posix-rename@openssh.com extension.
109
110
**Usage Examples:**
111
112
```javascript
113
// Atomic file rename (overwrites destination if exists)
114
await sftp.posixRename('/remote/temp.txt', '/remote/final.txt');
115
116
// Atomic directory rename
117
await sftp.posixRename('/remote/temp-dir', '/remote/final-dir');
118
119
// Safe atomic rename with server capability check
120
try {
121
await sftp.posixRename('/remote/source.dat', '/remote/target.dat');
122
console.log('Atomic rename completed');
123
} catch (err) {
124
if (err.message.includes('not supported')) {
125
console.log('Server does not support POSIX rename, using regular rename');
126
await sftp.rename('/remote/source.dat', '/remote/target.dat');
127
} else {
128
throw err;
129
}
130
}
131
```
132
133
### Change Permissions
134
135
Changes file or directory permissions on the remote server.
136
137
```javascript { .api }
138
/**
139
* Change permissions of remote file or directory
140
* @param rPath - Path to remote file/directory
141
* @param mode - New permissions (octal number or string)
142
* @param addListeners - Whether to add event listeners (default: true)
143
* @returns Promise resolving to success message
144
*/
145
chmod(rPath, mode, addListeners = true): Promise<String>;
146
```
147
148
**Usage Examples:**
149
150
```javascript
151
// Set file permissions using octal notation
152
await sftp.chmod('/remote/script.sh', 0o755); // rwxr-xr-x
153
154
// Set permissions using string notation
155
await sftp.chmod('/remote/data.txt', '644'); // rw-r--r--
156
157
// Make file executable
158
await sftp.chmod('/remote/program', 0o755);
159
160
// Remove write permissions for group and others
161
await sftp.chmod('/remote/private.txt', 0o600); // rw-------
162
163
// Bulk permission changes
164
const scripts = await sftp.list('/remote/scripts');
165
for (const file of scripts) {
166
if (file.type === '-' && file.name.endsWith('.sh')) {
167
await sftp.chmod(`/remote/scripts/${file.name}`, 0o755);
168
console.log(`Made ${file.name} executable`);
169
}
170
}
171
```
172
173
### Remote Copy
174
175
Creates a copy of a remote file on the remote server without downloading/uploading.
176
177
```javascript { .api }
178
/**
179
* Create a remote copy of a remote file
180
* @param src - Source file path on remote server
181
* @param dst - Destination file path on remote server
182
* @returns Promise resolving to success message
183
*/
184
rcopy(src, dst): Promise<String>;
185
```
186
187
**Usage Examples:**
188
189
```javascript
190
// Create backup copy
191
await sftp.rcopy('/remote/important.txt', '/remote/important.txt.backup');
192
193
// Copy to different directory
194
await sftp.rcopy('/remote/config.json', '/remote/backup/config.json');
195
196
// Copy with timestamp
197
const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
198
const backupName = `/remote/data-${timestamp}.json`;
199
await sftp.rcopy('/remote/data.json', backupName);
200
201
// Safe copy with checks
202
const source = '/remote/master.conf';
203
const backup = '/remote/master.conf.bak';
204
205
const sourceExists = await sftp.exists(source);
206
const backupExists = await sftp.exists(backup);
207
208
if (sourceExists === '-') {
209
if (backupExists !== false) {
210
// Remove old backup first
211
await sftp.delete(backup);
212
}
213
await sftp.rcopy(source, backup);
214
console.log('Backup created successfully');
215
}
216
```
217
218
## Permission Management
219
220
### Octal Permission Values
221
222
Common permission patterns:
223
224
```javascript
225
// File permissions
226
0o644 // rw-r--r-- (readable by all, writable by owner)
227
0o600 // rw------- (readable/writable by owner only)
228
0o755 // rwxr-xr-x (executable by all, writable by owner)
229
0o700 // rwx------ (full access by owner only)
230
231
// Directory permissions
232
0o755 // rwxr-xr-x (standard directory permissions)
233
0o750 // rwxr-x--- (accessible by owner and group)
234
0o700 // rwx------ (accessible by owner only)
235
```
236
237
### Permission Checking and Setting
238
239
```javascript
240
// Check current permissions before changing
241
const stats = await sftp.stat('/remote/file.txt');
242
const currentMode = stats.mode & parseInt('777', 8);
243
console.log(`Current permissions: ${currentMode.toString(8)}`);
244
245
// Set restrictive permissions for sensitive files
246
if (stats.isFile && currentMode !== 0o600) {
247
await sftp.chmod('/remote/file.txt', 0o600);
248
console.log('Set restrictive permissions');
249
}
250
```
251
252
## Advanced File Management Patterns
253
254
### Atomic File Updates
255
256
```javascript
257
// Safe file update pattern using temporary file and rename
258
const targetFile = '/remote/config.json';
259
const tempFile = `/remote/config.json.tmp.${Date.now()}`;
260
261
try {
262
// Upload new content to temporary file
263
await sftp.put('/local/new-config.json', tempFile);
264
265
// Verify upload succeeded
266
const exists = await sftp.exists(tempFile);
267
if (exists === '-') {
268
// Atomically replace original file
269
await sftp.posixRename(tempFile, targetFile);
270
console.log('File updated atomically');
271
}
272
} catch (err) {
273
// Clean up temporary file on error
274
await sftp.delete(tempFile, true);
275
throw err;
276
}
277
```
278
279
### Backup Before Modify
280
281
```javascript
282
// Create backup before modifying important files
283
const originalFile = '/remote/database.conf';
284
const backupFile = `/remote/database.conf.backup.${Date.now()}`;
285
286
// Create backup
287
await sftp.rcopy(originalFile, backupFile);
288
289
try {
290
// Modify original file
291
await sftp.put('/local/new-database.conf', originalFile);
292
console.log('Configuration updated successfully');
293
} catch (err) {
294
// Restore from backup on error
295
console.log('Update failed, restoring backup');
296
await sftp.rename(backupFile, originalFile);
297
throw err;
298
}
299
```
300
301
### Cleanup Operations
302
303
```javascript
304
// Clean up old backup files
305
const backupPattern = /\.backup\.\d+$/;
306
const files = await sftp.list('/remote/backups');
307
308
const oldBackups = files.filter(file => {
309
if (file.type !== '-') return false;
310
if (!backupPattern.test(file.name)) return false;
311
312
// Keep backups newer than 7 days
313
const weekOld = Date.now() - (7 * 24 * 60 * 60 * 1000);
314
return file.modifyTime < weekOld;
315
});
316
317
for (const backup of oldBackups) {
318
await sftp.delete(`/remote/backups/${backup.name}`);
319
console.log(`Deleted old backup: ${backup.name}`);
320
}
321
```
322
323
## Error Handling
324
325
File management errors provide detailed context:
326
327
- `ENOENT`: File or directory does not exist
328
- `EACCES`: Permission denied
329
- `EEXIST`: Destination already exists (rename)
330
- `EISDIR`: Operation not supported on directory
331
- `ENOTDIR`: Parent is not a directory
332
- `EXDEV`: Cross-device operation not supported
333
- Server-specific errors for unsupported operations