File Operations Example
A real-world example demonstrating file operations with proper validation and error handling.
File Copy Command
csharp
using Promty;
using Promty.Attributes;
[Description("copy", "Copy a file from source to destination")]
public class CopyCommand : Command<CopyCommand.Args>
{
public class Args
{
[Description("source", "The source file path")]
public string Source { get; set; } = string.Empty;
[Description("destination", "The destination file path")]
public string Destination { get; set; } = string.Empty;
[FlagAlias("overwrite", 'o')]
[Description("Overwrite destination if it exists")]
public bool Overwrite { get; set; }
[FlagAlias("verbose", 'v')]
[Description("Show detailed output")]
public bool Verbose { get; set; }
[FlagAlias("create-dirs", 'c')]
[Description("Create destination directories if they don't exist")]
public bool CreateDirectories { get; set; }
}
public override Task<int> ExecuteAsync(Args args)
{
try
{
// Validate source file exists
if (!File.Exists(args.Source))
{
Console.WriteLine($"Error: Source file '{args.Source}' does not exist");
return Task.FromResult(1);
}
// Check if destination exists
if (File.Exists(args.Destination) && !args.Overwrite)
{
Console.WriteLine($"Error: Destination file '{args.Destination}' already exists");
Console.WriteLine("Use --overwrite to replace it");
return Task.FromResult(1);
}
// Create destination directory if needed
var destDir = Path.GetDirectoryName(args.Destination);
if (!string.IsNullOrEmpty(destDir) && !Directory.Exists(destDir))
{
if (args.CreateDirectories)
{
if (args.Verbose)
Console.WriteLine($"Creating directory: {destDir}");
Directory.CreateDirectory(destDir);
}
else
{
Console.WriteLine($"Error: Destination directory '{destDir}' does not exist");
Console.WriteLine("Use --create-dirs to create it automatically");
return Task.FromResult(1);
}
}
// Perform the copy
if (args.Verbose)
{
Console.WriteLine($"Copying: {args.Source}");
Console.WriteLine($"To: {args.Destination}");
if (args.Overwrite && File.Exists(args.Destination))
Console.WriteLine("Overwriting existing file");
}
File.Copy(args.Source, args.Destination, args.Overwrite);
// Success message
if (args.Verbose)
{
var fileInfo = new FileInfo(args.Destination);
Console.WriteLine($"Success! Copied {fileInfo.Length:N0} bytes");
}
else
{
Console.WriteLine($"Copied: {Path.GetFileName(args.Source)} -> {Path.GetFileName(args.Destination)}");
}
return Task.FromResult(0);
}
catch (UnauthorizedAccessException)
{
Console.WriteLine("Error: Access denied. Check file permissions.");
return Task.FromResult(1);
}
catch (IOException ex)
{
Console.WriteLine($"Error: {ex.Message}");
return Task.FromResult(1);
}
catch (Exception ex)
{
Console.WriteLine($"Unexpected error: {ex.Message}");
return Task.FromResult(2);
}
}
}Usage Examples
Basic copy
bash
dotnet run -- copy input.txt output.txtCopy with overwrite
bash
dotnet run -- copy source.txt destination.txt --overwriteVerbose output
bash
dotnet run -- copy file.txt backup.txt -vOutput:
Copying: file.txt
To: backup.txt
Success! Copied 1,234 bytesCreate destination directories
bash
dotnet run -- copy data.csv backups/2024/data.csv --create-dirs -vOutput:
Creating directory: backups/2024
Copying: data.csv
To: backups/2024/data.csv
Success! Copied 5,678 bytesCombined flags
bash
dotnet run -- copy app.log logs/$(date +%Y-%m-%d)/app.log -o -c -vError Handling
Source file doesn't exist
bash
dotnet run -- copy missing.txt output.txtOutput:
Error: Source file 'missing.txt' does not existExit code: 1
Destination already exists
bash
dotnet run -- copy input.txt existing.txtOutput:
Error: Destination file 'existing.txt' already exists
Use --overwrite to replace itExit code: 1
Destination directory doesn't exist
bash
dotnet run -- copy file.txt folder/file.txtOutput:
Error: Destination directory 'folder' does not exist
Use --create-dirs to create it automaticallyExit code: 1
Permission denied
bash
dotnet run -- copy file.txt /root/protected.txtOutput:
Error: Access denied. Check file permissions.Exit code: 1
Help Text
bash
dotnet run -- copy --helpOutput:
Usage: copy <source> <destination> [options]
Copy a file from source to destination
Arguments:
<source> The source file path
<destination> The destination file path
Options:
-o, --overwrite Overwrite destination if it exists
-v, --verbose Show detailed output
-c, --create-dirs Create destination directories if they don't existKey Features Demonstrated
- ✅ Multiple positional arguments
- ✅ Input validation
- ✅ Comprehensive error handling
- ✅ User-friendly error messages
- ✅ Verbose mode for debugging
- ✅ Proper exit codes
- ✅ File system operations
- ✅ Helpful usage hints
Extended Features
You could extend this command with:
- Progress reporting for large files
- Recursive directory copying
- Pattern matching (wildcards)
- Preserve file attributes
- Dry-run mode
- Backup existing files
Example with dry-run:
csharp
[FlagAlias("dry-run", 'n')]
[Description("Show what would be copied without actually copying")]
public bool DryRun { get; set; }
// In ExecuteAsync:
if (args.DryRun)
{
Console.WriteLine("DRY RUN - No files will be copied");
Console.WriteLine($"Would copy: {args.Source} -> {args.Destination}");
return Task.FromResult(0);
}