@involvex/rmdir-cli 2.0.7 → 2.0.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -20,7 +20,60 @@ rmdir <dir>
20
20
  npx @involvex/rmdir-cli <dir>
21
21
  ```
22
22
 
23
- ## Parameter
23
+ ## Parameters
24
24
 
25
25
  - `-h`, `--help` - output usage information
26
26
  - `-v`, `--version` - output the version number
27
+ - `-f`, `--force` - enable recursive deletion of non-empty directories (requires confirmation)
28
+ - `-y`, `--yes` - skip confirmation prompts (non-interactive mode)
29
+
30
+ ## Usage Examples
31
+
32
+ ### Basic Usage
33
+
34
+ ```bash
35
+ # Delete an empty directory
36
+ rmdir mydir
37
+
38
+ # Delete a non-empty directory with confirmation prompt
39
+ rmdir --force mydir
40
+
41
+ # Delete a non-empty directory without confirmation
42
+ rmdir --force --yes mydir
43
+
44
+ # Delete multiple directories
45
+ rmdir --force dir1 dir2 dir3
46
+ ```
47
+
48
+ ### Safety Features
49
+
50
+ The `--force` parameter enables recursive deletion of non-empty directories, but includes safety measures:
51
+
52
+ 1. **Confirmation Prompt**: By default, the CLI will prompt for confirmation before deleting non-empty directories
53
+ 2. **Non-Interactive Mode**: Use `--yes` to skip confirmation prompts for automated scripts
54
+ 3. **Error Handling**: Clear error messages for permission issues, non-existent directories, or invalid paths
55
+ 4. **Progress Information**: Shows directory size and file count before deletion
56
+
57
+ ### Help Information
58
+
59
+ ```bash
60
+ rmdir --help
61
+ ```
62
+
63
+ Output:
64
+
65
+ ```bash
66
+ Usage: rmdir [options] <dir> [dir2 ...]
67
+
68
+ Options:
69
+ -h, --help output usage information
70
+ -v, --version output the version number
71
+ -f, --force enable recursive deletion of non-empty directories
72
+ -y, --yes skip confirmation prompts (non-interactive mode)
73
+
74
+ Examples:
75
+ rmdir mydir # Delete empty directory
76
+ rmdir --force mydir # Delete non-empty directory with confirmation
77
+ rmdir --force --yes mydir # Delete non-empty directory without confirmation
78
+ rmdir --force dir1 dir2 dir3 # Delete multiple directories
79
+ ```
package/bin/rmdir-cli.js CHANGED
@@ -3,16 +3,270 @@
3
3
  "use strict";
4
4
  var rmdir = require("../index");
5
5
  var version = require("../package.json").version;
6
+ var fs = require("fs");
7
+ var path = require("path");
6
8
 
7
- if (process.argv[2] == "--help" || process.argv[2] == "-h") {
8
- console.log("Usage: rmdir <dir>");
9
- console.log("rmdir <dir> - Recursively removes a directory.");
9
+ // Parse command line arguments
10
+ function parseArgs() {
11
+ var args = process.argv.slice(2);
12
+ var options = {
13
+ force: false,
14
+ yes: false,
15
+ help: false,
16
+ version: false,
17
+ directories: [],
18
+ };
19
+
20
+ for (var i = 0; i < args.length; i++) {
21
+ var arg = args[i];
22
+
23
+ if (arg === "--help" || arg === "-h") {
24
+ options.help = true;
25
+ } else if (arg === "--version" || arg === "-v") {
26
+ options.version = true;
27
+ } else if (arg === "--force" || arg === "-f") {
28
+ options.force = true;
29
+ } else if (arg === "--yes" || arg === "-y") {
30
+ options.yes = true;
31
+ } else if (arg.startsWith("-")) {
32
+ console.error("Unknown option: " + arg);
33
+ showUsage();
34
+ process.exit(1);
35
+ } else {
36
+ options.directories.push(arg);
37
+ }
38
+ }
39
+
40
+ return options;
41
+ }
42
+
43
+ // Show usage information
44
+ function showUsage() {
45
+ console.log("Usage: rmdir [options] <dir> [dir2 ...]");
46
+ console.log("");
47
+ console.log("Options:");
48
+ console.log(" -h, --help output usage information");
49
+ console.log(" -v, --version output the version number");
50
+ console.log(
51
+ " -f, --force enable recursive deletion of non-empty directories",
52
+ );
53
+ console.log(
54
+ " -y, --yes skip confirmation prompts (non-interactive mode)",
55
+ );
56
+ console.log("");
57
+ console.log("Examples:");
58
+ console.log(" rmdir mydir # Delete empty directory");
59
+ console.log(
60
+ " rmdir --force mydir # Delete non-empty directory with confirmation",
61
+ );
62
+ console.log(
63
+ " rmdir --force --yes mydir # Delete non-empty directory without confirmation",
64
+ );
65
+ console.log(" rmdir --force dir1 dir2 dir3 # Delete multiple directories");
66
+ }
67
+
68
+ // Show version information
69
+ function showVersion() {
70
+ console.log("rmdir-cli version: " + version);
71
+ }
72
+
73
+ // Check if directory exists and is accessible
74
+ function checkDirectory(dirpath) {
75
+ try {
76
+ var stats = fs.statSync(dirpath);
77
+ if (!stats.isDirectory()) {
78
+ console.error("Error: " + dirpath + " is not a directory");
79
+ return false;
80
+ }
81
+ return true;
82
+ } catch (err) {
83
+ if (err.code === "ENOENT") {
84
+ console.error("Error: Directory '" + dirpath + "' does not exist");
85
+ return false;
86
+ } else if (err.code === "EACCES") {
87
+ console.error("Error: Permission denied accessing '" + dirpath + "'");
88
+ return false;
89
+ } else {
90
+ console.error(
91
+ "Error: Unable to access '" + dirpath + "': " + err.message,
92
+ );
93
+ return false;
94
+ }
95
+ }
96
+ }
97
+
98
+ // Check if directory is empty
99
+ function isDirectoryEmpty(dirpath) {
100
+ try {
101
+ var files = fs.readdirSync(dirpath);
102
+ return files.length === 0;
103
+ } catch (ignoreErr) {
104
+ console.log("Error:", ignoreErr);
105
+ return false;
106
+ }
107
+ }
108
+
109
+ // Get directory size for progress indication
110
+ function getDirectorySize(dirpath) {
111
+ var totalSize = 0;
112
+ var totalFiles = 0;
113
+
114
+ function walkDir(currentPath) {
115
+ try {
116
+ var files = fs.readdirSync(currentPath);
117
+ files.forEach(function (file) {
118
+ var filePath = path.join(currentPath, file);
119
+ var stats = fs.statSync(filePath);
120
+
121
+ if (stats.isDirectory()) {
122
+ walkDir(filePath);
123
+ } else {
124
+ totalSize += stats.size;
125
+ totalFiles++;
126
+ }
127
+ });
128
+ } catch (calcErr) {
129
+ console.log("Error:", calcErr);
130
+ // Ignore errors when calculating size
131
+ }
132
+ }
133
+
134
+ walkDir(dirpath);
135
+ return { size: totalSize, files: totalFiles };
136
+ }
137
+
138
+ // Confirm deletion with user
139
+ function confirmDeletion(dirpath, options) {
140
+ if (options.yes) {
141
+ return Promise.resolve(true);
142
+ }
143
+
144
+ var readline = require("readline");
145
+ var rl = readline.createInterface({
146
+ input: process.stdin,
147
+ output: process.stdout,
148
+ });
149
+
150
+ return new Promise(function (resolve) {
151
+ var sizeInfo = getDirectorySize(dirpath);
152
+ var sizeMB = (sizeInfo.size / (1024 * 1024)).toFixed(2);
153
+
154
+ console.log("About to delete: " + dirpath);
155
+ console.log(
156
+ "Directory contains: " + sizeInfo.files + " files, " + sizeMB + " MB",
157
+ );
158
+ console.log("");
159
+
160
+ rl.question(
161
+ "Are you sure you want to delete this directory? [y/N]: ",
162
+ function (answer) {
163
+ rl.close();
164
+ var confirmed =
165
+ answer.toLowerCase() === "y" || answer.toLowerCase() === "yes";
166
+ if (!confirmed) {
167
+ console.log("Operation cancelled.");
168
+ }
169
+ resolve(confirmed);
170
+ },
171
+ );
172
+ });
173
+ }
174
+
175
+ // Enhanced rmdir function with progress and confirmation
176
+ function rmdirWithConfirmation(dirpath, options) {
177
+ return new Promise(function (resolve, reject) {
178
+ if (!checkDirectory(dirpath)) {
179
+ reject(new Error("Directory check failed"));
180
+ return;
181
+ }
182
+
183
+ var isEmpty = isDirectoryEmpty(dirpath);
184
+
185
+ if (!isEmpty && !options.force) {
186
+ console.error("Error: Directory '" + dirpath + "' is not empty.");
187
+ console.error("Use --force to delete non-empty directories.");
188
+ reject(new Error("Directory not empty"));
189
+ return;
190
+ }
191
+
192
+ if (!isEmpty) {
193
+ confirmDeletion(dirpath, options)
194
+ .then(function (confirmed) {
195
+ if (!confirmed) {
196
+ resolve(false);
197
+ return;
198
+ }
199
+
200
+ console.log("Deleting directory: " + dirpath);
201
+ try {
202
+ rmdir(dirpath);
203
+ console.log("Successfully deleted: " + dirpath);
204
+ resolve(true);
205
+ } catch (err) {
206
+ console.error(
207
+ "Error deleting directory '" + dirpath + "': " + err.message,
208
+ );
209
+ reject(err);
210
+ }
211
+ })
212
+ .catch(function (err) {
213
+ reject(err);
214
+ });
215
+ } else {
216
+ try {
217
+ rmdir(dirpath);
218
+ console.log("Successfully deleted: " + dirpath);
219
+ resolve(true);
220
+ } catch (err) {
221
+ console.error(
222
+ "Error deleting directory '" + dirpath + "': " + err.message,
223
+ );
224
+ reject(err);
225
+ }
226
+ }
227
+ });
228
+ }
229
+
230
+ // Main execution
231
+ var options = parseArgs();
232
+
233
+ if (options.help) {
234
+ showUsage();
10
235
  process.exit(0);
11
- } else if (process.argv[2] == "--version" || process.argv[2] == "-v") {
12
- console.log(version);
236
+ } else if (options.version) {
237
+ showVersion();
13
238
  process.exit(0);
239
+ } else if (options.directories.length === 0) {
240
+ console.error("Error: No directory specified");
241
+ showUsage();
242
+ process.exit(1);
14
243
  } else {
15
- if (process.argv[2]) {
16
- rmdir(process.argv[2]);
17
- }
244
+ // Process each directory
245
+ var promises = options.directories.map(function (dirpath) {
246
+ return rmdirWithConfirmation(dirpath, options);
247
+ });
248
+
249
+ Promise.all(promises)
250
+ .then(function (results) {
251
+ var successCount = results.filter(Boolean).length;
252
+ var totalCount = results.length;
253
+
254
+ if (successCount === totalCount) {
255
+ console.log("\nAll directories deleted successfully.");
256
+ process.exit(0);
257
+ } else {
258
+ console.log(
259
+ "\n" +
260
+ successCount +
261
+ " out of " +
262
+ totalCount +
263
+ " directories deleted successfully.",
264
+ );
265
+ process.exit(1);
266
+ }
267
+ })
268
+ .catch(function (err) {
269
+ console.error("Operation failed:", err.message);
270
+ process.exit(1);
271
+ });
18
272
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@involvex/rmdir-cli",
3
- "version": "2.0.7",
3
+ "version": "2.0.8",
4
4
  "description": "rmdir-cli is cross-platform command to recursively delete directories",
5
5
  "keywords": [
6
6
  "rmdir",