Skip to content

jomaxso/Reshape

Repository files navigation

🔄 Reshape CLI

Batch rename files using metadata patterns - A powerful dual-mode file renaming tool with both CLI and Web UI.

Release .NET 10 Vue 3 TypeScript License

✨ Features

  • 🖥️ Dual Mode: Use via CLI commands or modern Web UI
  • 📷 EXIF Metadata Extraction: Extract date, camera info, GPS coordinates from images
  • 🏝️ Vacation Mode: Organize photos into day-based folder structures
  • 🌍 GPS & Timezone Support: Automatic timezone detection from GPS coordinates
  • 🔄 Pattern-based Renaming: Flexible patterns with placeholders
  • 👁️ Preview Mode: See changes before executing
  • AOT Compiled: Fast startup with Native AOT compilation
  • 🎨 Beautiful CLI Output: Powered by Spectre.Console

📋 Table of Contents

📦 Installation

Quick Install (Recommended)

Windows (PowerShell)

iex "& { $(irm https://raw.githubusercontent.com/jomaxso/Reshape/main/eng/scripts/install.ps1) }"

This automatically installs Reshape and adds it to your user PATH. Restart your terminal after installation.

Linux / macOS (Bash)

curl -fsSL https://raw.githubusercontent.com/jomaxso/Reshape/main/eng/scripts/install.sh | bash

Follow the on-screen instructions to add Reshape to your PATH.

Note: Having issues with PATH? See PATH Setup Guide for troubleshooting.

Install Specific Version

Windows

iex "& { $(irm https://raw.githubusercontent.com/jomaxso/Reshape/main/eng/scripts/install.ps1) } -Version v0.1.0"

Linux / macOS

curl -fsSL https://raw.githubusercontent.com/jomaxso/Reshape/main/eng/scripts/install.sh | bash -s -- --version v0.1.0

Update to Latest Version

If you already have Reshape installed, you can update it using:

reshape update

Manual Installation from Releases

Download the latest release for your platform from the Releases page:

  • Windows: reshape-win-x64.zip
  • Linux: reshape-linux-x64.tar.gz
  • macOS (ARM): reshape-osx-arm64.tar.gz

Extract the archive and add the executable to your PATH.

Build from Source

Prerequisites

Quick Build

Use the automated build script:

# Windows (PowerShell)
.\build.ps1

# Linux / macOS
./build.sh

Manual Steps

# Clone the repository
git clone https://github.com/jomaxso/Reshape.git
cd Reshape

# Build the Vue UI first (required!)
cd src/Reshape.Ui
npm install
npm run build

# Build the CLI
cd ../Reshape.Cli
dotnet build

Publish as Native Executable

# Using build script (recommended)
.\build.ps1 -Configuration Release -Runtime win-x64

# Manual publish
cd src/Reshape.Cli
dotnet publish -c Release -r <RID> --self-contained
# Replace <RID> with: win-x64, linux-x64, or osx-arm64

🧪 Testing Pull Requests

Want to try out a feature before it's merged? Each pull request automatically gets a comment with installation instructions!

When you open a PR, GitHub Actions will automatically:

  • ✅ Build the code for all platforms (Windows, Linux, macOS)
  • 📦 Create downloadable artifacts
  • 💬 Post a comment with detailed installation instructions

Just check the PR comments for the "🚀 Test This Pull Request" section with:

  • Direct links to download pre-built binaries
  • Instructions for building locally from the PR branch
  • Quick start examples specific to that PR

This makes it easy for maintainers and contributors to test changes before merging!

🚀 Quick Start

CLI Mode

# List files in a folder
dotnet run --project src/Reshape.Cli/ -- file list --path "C:\Photos" --ext .jpg .png

# Preview rename operations
dotnet run --project src/Reshape.Cli/ -- file preview --path "C:\Photos" --pattern "{year}-{month}-{day}_{filename}" --ext .jpg

# Execute rename (interactive - will prompt for confirmation)
dotnet run --project src/Reshape.Cli/ -- file rename --path "C:\Photos" --pattern "{year}-{month}-{day}_{filename}" --ext .jpg

# Execute rename without confirmation prompt
dotnet run --project src/Reshape.Cli/ -- file rename --path "C:\Photos" --pattern "{year}-{month}-{day}_{filename}" --ext .jpg --no-interactive

# Show available patterns
dotnet run --project src/Reshape.Cli/ -- pattern list

Web UI Mode

# Start the web server
dotnet run --project src/Reshape.Cli/ -- run

# Open browser at http://localhost:5000

💻 CLI Commands

Command Description Example
run Start the Web UI server reshape run
file list List files in a folder reshape file list --path ./photos --ext .jpg .png
file preview Preview rename operations reshape file preview --path ./photos --pattern "{date_taken}_{filename}"
file rename Execute rename operations reshape file rename --path ./photos --pattern "{year}/{month}/{filename}"
pattern list Show available pattern templates reshape pattern list
pattern set Add a custom pattern reshape pattern set "{pattern}" "Description"
pattern remove Remove a custom pattern reshape pattern remove "{pattern}"
update Update to the latest version reshape update

Update Command Options

Option Description
--check Check for updates without installing
--prerelease Include prerelease versions
--stable Only update to stable releases (default)

Common Options

Option Description
--path Folder path to process
--ext Filter by file extensions (e.g., .jpg .png .heic)
--pattern Rename pattern with placeholders
--no-interactive Skip confirmation prompts and execute automatically

🌐 Web UI

The Web UI provides an intuitive interface for:

  • 📁 Browsing and selecting folders
  • 🔍 Scanning files with metadata preview
  • ✏️ Building rename patterns visually
  • 👁️ Live preview of rename operations
  • 🏝️ Vacation mode configuration
  • ✅ Selective file processing

Web UI Screenshot

🎯 Patterns & Placeholders

Available Placeholders

Placeholder Description Example
{filename} Original filename (without extension) IMG_0001
{ext} File extension (without dot) jpg
{year} Year (4 digits) 2024
{month} Month (2 digits) 01
{day} Day (2 digits) 15
{date_taken} EXIF date taken 2024-01-15
{time_taken} EXIF time taken 14-30-00
{camera_make} Camera manufacturer Canon
{camera_model} Camera model EOS_R5
{width} Image width 4000
{height} Image height 3000
{counter:N} Counter with N-digit padding 001, 0001
{gps_lat} GPS latitude 48.858844
{gps_lon} GPS longitude 2.294351

Pattern Examples

# Date prefix
{year}-{month}-{day}_{filename}
→ 2024-01-15_IMG_0001.jpg

# Camera + date + counter
{camera_model}_{date_taken}_{counter:4}
→ iPhone15_2024-01-15_0001.jpg

# Standard format
IMG_{year}{month}{day}_{counter:4}
→ IMG_20240115_0001.jpg

# Organized by date folders
{year}/{month}/{filename}
→ 2024/01/IMG_0001.jpg

🏝️ Vacation Mode

Vacation Mode is designed for organizing holiday photos into day-based folder structures.

Features

  • 📅 Automatic day grouping based on photo dates
  • 🌍 GPS-based timezone detection
  • 📁 Customizable folder structure
  • 🔢 Day-specific counters

Vacation-Specific Placeholders

Placeholder Description Example
{day_number} Day of vacation (1, 2, 3...) 1
{day_counter} Counter within a day 001
{global_counter} Global counter across all days 0001

Example Output

Tag 1/
  ├─ 2024-07-15_001.jpg
  ├─ 2024-07-15_002.jpg
  └─ 2024-07-15_003.jpg
Tag 2/
  ├─ 2024-07-16_001.jpg
  └─ 2024-07-16_002.jpg
Tag 3/
  └─ 2024-07-17_001.jpg

📖 See VACATION_MODE.md for detailed documentation.

🛠️ Development

Project Structure

Reshape/
├── src/
│   ├── Reshape.Cli/           # .NET 10 CLI with embedded web server
│   │   ├── Commands/          # CLI commands
│   │   │   ├── Files/         # File operation commands (list, preview, rename)
│   │   │   ├── Patterns/      # Pattern-related commands
│   │   │   ├── RunCommand.cs  # Web server command (serve)
│   │   │   └── UpdateCommand.cs # Self-update command
│   │   ├── Utilities/         # Helper classes
│   │   ├── wwwroot/           # Compiled Vue app (auto-generated)
│   │   ├── Program.cs         # Entry point
│   │   ├── FileService.cs     # Core file operations
│   │   └── Models.cs          # Data models
│   │
│   └── Reshape.Ui/            # Vue 3 + TypeScript frontend
│       ├── src/
│       │   ├── components/    # Vue components
│       │   ├── api.ts         # API client
│       │   └── types.ts       # TypeScript types
│       └── vite.config.ts     # Build configuration
│
├── tests/
│   └── Reshape.Cli.Tests/    # xUnit test project
│       ├── Models/            # Model tests
│       ├── Services/          # Service tests
│       └── Utilities/         # Utility tests
│
├── docs/                      # Documentation
└── eng/                       # Build and versioning configuration

Development Workflow

# Terminal 1: Start CLI in watch mode
cd src/Reshape.Cli
dotnet watch run -- serve

# Terminal 2: Start Vue dev server (optional, for hot reload)
cd src/Reshape.Ui
npm run dev

Testing

The project uses xUnit with Shouldly assertions following the Arrange // Act // Assert pattern.

Running Tests

# Run all tests
dotnet test

# Run tests with coverage
dotnet test --collect:"XPlat Code Coverage"

# Run tests in watch mode
dotnet watch test

Writing Tests

All tests follow the Arrange // Act // Assert pattern:

[Fact]
public void FormatSize_ShouldFormatBytesCorrectly()
{
    // Arrange
    long bytes = 1024;

    // Act
    var result = FormatHelper.FormatSize(bytes);

    // Assert
    result.ShouldBe("1 KB");
}

Coverage Requirements

  • Minimum coverage: 19% (excluding auto-generated code)
  • CI pipeline enforces coverage threshold
  • Coverage reports are generated for all PRs
  • Auto-generated files (JSON serialization context) are excluded from coverage
  • Target: Increase coverage over time as more tests are added

Test Structure

  • Models/ - Tests for data models and records
  • Services/ - Tests for FileService and business logic
  • Utilities/ - Tests for helper classes
  • Follow xUnit naming conventions
  • Use Shouldly for fluent assertions

Building for Production

# Build Vue UI first
cd src/Reshape.Ui
npm run build

# Build CLI (UI is embedded in wwwroot/)
cd ../Reshape.Cli
dotnet publish -c Release

AOT Compilation

The CLI supports Native AOT compilation for fast startup:

dotnet publish -c Release -r win-x64 --self-contained

⚠️ Important: All JSON types must be registered in AppJsonSerializerContext.cs for AOT compatibility.

📚 Documentation

Document Description
README.md This file - overview and quick start
VACATION_MODE.md Vacation mode detailed documentation
docs/CICD.md CI/CD pipeline and release workflow
docs/CLI.md CLI reference documentation
docs/API.md REST API documentation
docs/DEVELOPMENT.md Development guide
src/Reshape.Cli/ARCHITECTURE.md Code architecture overview

🤝 Contributing

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

Please read our Contributing Guide for details.

📄 License

This project is licensed under the MIT License - see the LICENCE.txt file for details.

� Versioning

Reshape follows Semantic Versioning with centralized version management. See VERSIONING.md for details on:

  • How versions are managed in eng/Versions.props
  • Automated nightly version bumps
  • Release workflows and processes

�🙏 Acknowledgments


Made with ❤️ by jomaxso

About

Batch rename files using metadata patterns - A powerful dual-mode file renaming tool with both CLI and Web UI.

Resources

License

Contributing

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors