A command-line utility to create ZIP archives from directories with selective inclusion/exclusion of files and directories. Supports local file output, network file share destination, or email delivery via SMTP.
- Recursive directory traversal with selective filtering
- Exclude by:
- File extensions (e.g.,
.bmp,.jpg) - Directory names (e.g.,
.git,node_modules) - Specific filenames
- File extensions (e.g.,
- Multiple output modes:
- Local file system
- Network file share (UNC paths)
- Email via SMTP
- Clean SOLID architecture with pluggable output providers
- Fully commented code for educational purposes
- .NET 7.0 or later
- Installed .NET SDK
dotnet restore
dotnet builddotnet run -- \
--source "C:\folder\to\zip" \
--zip "output.zip" \
--output localFile \
--target "C:\output\path" \
--exclude-ext ".bmp,.jpg" \
--exclude-dir ".git,node_modules" \
--exclude-files "README.md,secret.txt"dotnet run -- \
--source "C:\folder\to\zip" \
--zip "output.zip" \
--output filesShare \
--target "\\server\share\path"dotnet run -- \
--source "C:\folder\to\zip" \
--zip "output.zip" \
--output smtp \
--smtp-host "smtp.example.com" \
--smtp-port 587 \
--smtp-from "sender@example.com" \
--smtp-to "recipient@example.com" \
--smtp-ssl true \
--smtp-user "username" \
--smtp-password "password"dotnet run --project ZipTool.Tests\ZipTool.Tests.csprojExpected output:
RunCreateZipTest passed.
RunParseOptionsTest passed.
All tests passed.
├── Program.cs # Main entry point & flow
├── Core/
│ ├── CommandLineOptions.cs # Argument parser & validation
│ ├── ZipService.cs # ZIP creation logic
│ └── Outputs/
│ ├── IOutputProvider.cs # Interface for output strategies
│ ├── OutputManager.cs # Dispatcher for output modes
│ ├── LocalFileOutputProvider.cs # Save to local disk
│ ├── FileShareOutputProvider.cs # Save to network share
│ └── SmtpOutputProvider.cs # Send via email
└── ZipTool.Tests/
└── Program.cs # Console-based test harness
Design Patterns Used:
- Strategy Pattern: Output providers implement
IOutputProviderinterface - Factory/Dispatcher:
OutputManagerselects provider based onOutputMode - Dependency Injection (manual): Services passed to orchestrator
Why This Design: Adding a new output method (e.g., AWS S3, FTP) requires:
- Implementing
IOutputProviderin a new file - Adding new case to
OutputManager.Publish()
No changes to core ZIP logic needed.
- Record types (
CommandLineOptionswithrequiredfields) - Nullable reference types (
string?,#nullable enable) - Extension methods & LINQ
- IDisposable pattern for resource cleanup
- Sealed classes for security & optimization
Q: How would you add a new output format?
A: Implement IOutputProvider, add case to OutputManager switch statement.
Q: How do you handle file exclusions?
A: Recursive predicate checks in IsDirectoryExcluded() and IsFileExcluded().
Q: Why use interfaces over inheritance?
A: Decouples output concerns, easier testing, supports composition over inheritance.
- Code is heavily commented for readability (transition from Python to C#)
- Error handling: Validation in
CommandLineOptions.Parse(), exception propagation - Testing: Manual console harness (avoid test framework compatibility issues)
- Framework: .NET 7.0 for stability; upgradeable to .NET 8 or 10
Author: Created for technical interview exercise
Language: C# 14
Platform: .NET 7.0+