A powerful, Rust-based CNP (Canopy) ecosystem tool that replaces the standard Unix mv command with intelligent filename transformation capabilities and full CNP grammar support.
- POSIX-compatible mv/cp commands with all standard flags (-r, -f, -n, -L, -P, --preserve)
- Drop-in replacement for the standard Unix
mvcommand - CNP Grammar Support - Full Canopy ecosystem integration with filters, routes, and tool delegation
- Interactive REPL Interface with command history and tab completion
- Smart File Renaming with multiple transformation strategies:
- Convert to snake_case (
document-name.pdf→document_name.pdf) - Convert to kebab-case (
document_name.pdf→document-name.pdf) - Convert to Title Case (
document_name.pdf→Document Name.pdf) - Convert to camelCase (
document_name.pdf→documentName.pdf) - Convert to PascalCase (
document_name.pdf→DocumentName.pdf) - Convert to lowercase or UPPERCASE
- Clean up spaces and special characters
- Split camelCase/PascalCase then apply any transformation (
featureWishList.md→feature_wish_list.md)
- Convert to snake_case (
- Filter Keywords:
NAME:,TYPE:,EXT:,SIZE:,DEPTH:,MODIFIED:,ACCESSED: - Semantic Groups:
FOR:notes,FOR:media,FOR:scripts,FOR:projects,FOR:configs - Tool Delegation:
TO:say,TO:dff,TO:xfd,TO:dscfor specialized operations - Output Routing:
INTO:file.txt,FORMAT:json/csv/yamlfor structured output - Advanced Filtering: Complex file discovery with logical grouping
- Directory Organization:
- Group files by basename into directories
- Flatten directory structures by moving all files to the root
- Clean up empty directories after flattening
- Preview Mode - See changes before they're applied, with detailed source → destination mapping and deduplication annotations
- Batch Processing - Apply transformations to multiple files at once
- Undo Functionality - Safely revert changes
- Safety Features - File backups and conflict detection
cargo install smv# Clone the repository
git clone https://github.com/jwliles/smv.git
cd smv
# Build and install
cargo install --path .SMV supports the full CNP (Canopy) grammar for advanced file operations with filters, semantic groups, and tool delegation:
# Transform with extension filter
smv snake . EXT:md -p # Convert markdown files to snake_case
# Filter by file type
smv kebab . TYPE:file EXT:txt -r # Only process .txt files, recursively
# Use semantic groups
smv title . FOR:notes -p # Transform all note files (md, txt, etc.)
smv clean . FOR:media # Clean up media filenames
# Size-based filtering
smv pascal . SIZE>1MB TYPE:file -p # Large files only
# Date-based filtering
smv lower . MODIFIED>2024-01-01 -r # Files modified after Jan 1, 2024
# Prefix removal
smv CHANGE: "IMG_" INTO "" . EXT:jpg -p # Remove "IMG_" prefix from all JPG files
smv CHANGE: "DSC" INTO "" . EXT:png # Remove "DSC" prefix from PNG files
# Split camelCase/PascalCase then transform
smv split snake . EXT:md -p # Split camelCase files then convert to snake_case
smv split kebab . EXT:js TYPE:file # Split PascalCase files then convert to kebab-case# Tool delegation - delegate complex operations to specialized tools
smv snake . EXT:epub TO:say split_and_titlecase # Use SAY for word segmentation
smv organize . FOR:media TO:dff find_duplicates # Use DFF to find duplicate media
# Output routing - save results to files
smv clean . FOR:scripts INTO:cleaned_files.txt # Save file list to text file
smv title . TYPE:file FORMAT:json -p # Output as JSON format
# Complex filtering with multiple criteria
smv kebab . TYPE:file EXT:md SIZE<1MB NAME:draft -pSemantic groups provide an intelligent way to categorize files by their purpose rather than just file extensions:
FOR:notes- Documentation and note files (.md,.txt,.org,.rst,.adoc)FOR:media- Images, videos, and audio files (.jpg,.png,.mp4,.wav,.gif, etc.)FOR:scripts- Executable and source code files (.sh,.py,.rs,.js,.go, etc.)FOR:projects- Project directories and build files (Cargo.toml,package.json,.git/, etc.)FOR:configs- Configuration files (.yaml,.json,.toml,.ini,.conf, etc.)
These groups make it easy to operate on files by their semantic meaning:
# Clean up all documentation files in a project
smv clean . FOR:notes -r
# Convert all script filenames to snake_case
smv snake . FOR:scripts -p
# Organize all media files
smv title . FOR:mediaSMV provides full POSIX-compatible file operations with all standard flags:
# Move a file to another location
smv mv file.txt /path/to/destination/
# Move multiple files to a directory
smv mv file1.txt file2.txt destination_directory/
# Multi-source move with CNP grammar (regex or glob, deduplication, preview)
smv -move EXT:png FROM:a/,b/ TO:c/ -p
smv -move NAME:'^img\d+' FROM:a/,b/ TO:c/ -r -p
smv -move EXT:png FROM:a/*.png,b/*.png TO:c/ -gr -p
# Preview output shows:
# a/img1.png → c/img1.png [NEW]
# b/img2.png → c/img2.png [NEW]
# b/img3.png → c/img3.png [OVERWRITE]
# [DEDUP] b/img1.png matched multiple patterns, processed once
# Rename a file
smv mv old_name.txt new_name.txt
# Move with flags
smv mv source dest -f # Force overwrite
smv mv source dest -n # No-clobber (don't overwrite)
smv mv *.txt backup/ -r # Recursive move
smv mv file dest --interactive-confirm # Prompt before overwrite# Copy a file
smv cp file.txt backup/
# Copy multiple files
smv cp file1.txt file2.txt *.md backup/
# Copy directories recursively
smv cp source_dir/ backup_dir/ -r
# Copy with metadata preservation
smv cp important.txt backup/ --preserve
# Copy with symbolic link handling
smv cp -L symlink dest # Dereference symlinks
smv cp -P symlink dest # Preserve symlinks-r- Recursive (for directories)-f- Force (overwrite without confirmation)-n- No-clobber (never overwrite existing files)-L- Dereference symbolic links-P- Do not follow symbolic links--preserve- Preserve file attributes, ownership, and timestamps--interactive-confirm- Prompt before overwriting files
SMV follows the CNP command philosophy: <tool> [scope] [targets] [modifiers]
SMV features an Excel-like command guidance system that shows available options as you type:
$ smv snake EXT:pdf
[smv] [snake] [EXT:pdf] [-p|-r|-f]
cmd transform filters flags (optional)- F1: Get context-sensitive help for current position
- Tab: Cycle through valid options
- Backspace: Navigate to previous position
Apply transformations using the new sequential structure:
# Convert filenames to snake_case
smv -snake . txt
# Convert filenames to kebab-case with preview
smv -kebab . pdf preview
# Clean up spaces and special characters recursively
smv -clean /path/to/messy/files/ recursive
# Convert to Title Case for specific extensions
smv -title documents/ md txt
# Multiple file types with preview
smv -pascal . pdf txt docx previewOrganize or flatten directory structures:
# Group files by basename into directories
smv -group /path/to/files/
# Preview grouping without making changes
smv -group /path/to/files/ preview
# Flatten all files from subdirectories into the root directory
smv -flatten /path/to/nested/folders/
# Sort files by type with grouping
smv -sort downloads/ type groupSMV is designed to work within the CNP REPL environment:
# Start CNP REPL
$ cnp
CNP> smv snake EXT:pdf -p
CNP> smv pascal documents/ EXT:txt
CNP> exit
$Launch the interactive REPL interface:
# Start interactive session
smv -interactiveType exit to quit the REPL. All operations are saved to history automatically.
Launch the TUI file explorer with Vim-style navigation:
# Start TUI mode
smv -tuiThe TUI mode features:
- File explorer with Vim motions (hjkl, gg, G)
- Visual selection mode for multiple files
- Fuzzy search using Skim integration
- GParted-style operation queue
- Preview of file transformations
In the interactive shell:
smv> ls
document.pdf document.docx image.jpg notes.txt
smv> preview snake *.pdf
document.pdf → document.pdf (no change needed)
smv> rename notes.txt
...
Select transformation:
1. Clean up spaces and special characters
...
4. Convert to Title Case
...
Preview of changes:
"notes.txt" → "Notes.txt"
Apply these changes? [y/N] y
Renamed: "notes.txt" → "Notes.txt"
smv> undo
Operation undone successfully.
smv> help
Commands:
preview <transform> <files> - Show transformation without applying
apply <transform> <files> - Apply transformation
rename <files> --options - Interactive renaming wizard
undo - Revert last operation
cd <directory> - Change directory
ls [pattern] - List files
help - Show this help
quit - Exit program
smv <COMMAND> <PATH> [FILTERS] [ROUTES] [FLAGS]
Commands: snake, kebab, pascal, camel, title, lower, upper, clean, split TRANSFORMATION, CHANGE: "old" INTO "new", CHANGE: "prefix" INTO "" (prefix removal), REGEX "pattern" INTO "replacement"
Filters:
NAME:value- Match filenames containing valueTYPE:directory- Filter to directories only (files are default)EXT:extension- Filter by file extensionSIZE:1MB/SIZE:500KB- Filter by file sizeDEPTH:2/DEPTH:1- Filter by directory depthMODIFIED:2024-01-01/MODIFIED:2023-12-31- Filter by modification dateACCESSED:2024-01-01/ACCESSED:2023-12-31- Filter by access dateFOR:notes|media|scripts|projects|configs- Semantic file groups
Routes:
TO:tool- Delegate operation to another CNP tool (say, dff, xfd, dsc)INTO:filename- Save output to fileFORMAT:json|csv|yaml|text- Format output
Flags: -r (recursive), -p (preview), -f (force), -i (interactive), -T (TUI), -u (undo)
Options:
-i, --interactive Launch interactive REPL interface
-p, --preview Preview changes without applying them
-r, --recursive Process subdirectories recursively
-f, --force Skip confirmations
-T, --tui Launch terminal UI mode
-u, --undo Undo the last operation
--exclude <PATTERNS> Comma-separated patterns to exclude
--max-history-size <SIZE> Maximum number of operations in history [default: 50]
-h, --help Print help
-V, --version Print version
snake- Convert to snake_casekebab- Convert to kebab-casepascal- Convert to PascalCasecamel- Convert to camelCasetitle- Convert to Title Caselower- Convert to lowercaseupper- Convert to UPPERCASEclean- Clean up spaces and special characterssplit TRANSFORMATION- Split camelCase/PascalCase then apply transformation
| Transform | Description | Example |
|---|---|---|
clean |
Clean up spaces and special characters | My File (1).txt → My File 1.txt |
snake |
Convert to snake_case | My-File.txt → my_file.txt |
kebab |
Convert to kebab-case | My_File.txt → my-file.txt |
title |
Convert to Title Case | my_file.txt → My File.txt |
camel |
Convert to camelCase | my_file.txt → myFile.txt |
pascal |
Convert to PascalCase | my_file.txt → MyFile.txt |
lower |
Convert to lowercase | MyFile.txt → myfile.txt |
upper |
Convert to UPPERCASE | myFile.txt → MYFILE.TXT |
split snake |
Split camelCase/PascalCase then convert to snake_case | featureWishList.md → feature_wish_list.md |
split kebab |
Split camelCase/PascalCase then convert to kebab-case | UserSettings.json → user-settings.json |
split title |
Split camelCase/PascalCase then convert to Title Case | apiEndpoint.ts → ApiEndpoint.ts |
CHANGE: "prefix" INTO "" |
Remove prefix from filename | IMG_1234.jpg → 1234.jpg |
SMV automatically creates backups of modified files in ~/.config/smv/backups/. This allows the undo functionality to work even after the program has been closed and reopened.
The undo command reverts the most recent operation.
In interactive mode, you can use:
smv> undo
In command-line mode, you can use:
smv --undoSMV will not overwrite existing files unless explicitly instructed to do so, preventing accidental data loss.
- Rust (Minimum supported version: 1.85.0)
- GNU/Linux or other free operating system
- Standard system libraries
Note: SMV is developed exclusively for free operating systems. It is not officially tested or supported on proprietary platforms.
See DEVELOPMENT_PLAN.md for the current roadmap and development priorities.
- CNP Grammar Support: Full Canopy ecosystem integration with filters, routes, and tool delegation
- Advanced Filtering: NAME:, TYPE:, EXT:, SIZE:, DEPTH:, MODIFIED:, ACCESSED: filters
- Semantic Groups: FOR:notes, FOR:media, FOR:scripts, FOR:projects, FOR:configs
- Tool Delegation: TO:tool routing for specialized operations
- Output Routing: INTO:file and FORMAT:json/csv/yaml support
- DSC Integration: Ultra-fast file discovery using DSC instead of broken glob patterns
- New Command Structure: Implemented CNP command philosophy
- Interactive Guidance System: Excel-like command preview and help (designed)
- Sequential Command Parsing: Position-based argument validation
- CNP REPL Integration: Designed for use within CNP environment
- Simplified Syntax: No more
--clutter after scope declaration
- Interactive Guidance Implementation: Build the Excel-like command preview system
- F1 Help System: Context-sensitive help for each command position
- Tab Completion: Cycle through valid options at each position
- CNP Library Integration: Extract shared command guidance into CNP library
- Complete Tool Delegation: Finalize integration with SAY, DFF, XFD tools
- WHERE Filter Groups: Implement logical grouping of multiple filters
-
Multi-step transformation pipelines: Chain multiple transforms together
# Example: Clean, convert to snake_case, then replace spaces with underscores smv -pipeline "clean,snake,replace:space:_" file.txt
-
Regular expression-based transformations: Advanced pattern replacement
# Example: Replace "old" with "new" in filenames smv -replace "old:new" file.txt # Example: Replace all digits with 'X' smv -char-replace "digits:X" file*.txt
-
Custom user-defined transformations: Save your own transform combinations
# Example: Save a custom transformation smv -save "my-format:clean,snake,upper" # Use the custom transformation smv -custom my-format file.txt
-
Configuration file system: Persistent settings and defaults
-
Directory synchronization features: Keep renamed files in sync
-
Plugin system for add-ons: Extend functionality
-
Enhanced REPL with syntax highlighting: Improved interactive mode
-
Color-coded preview output: Visual differentiation of changes
MIT License