mirror of
https://github.com/rclone/rclone.git
synced 2025-12-06 00:03:32 +00:00
convmv: add convmv command
convmv supports advanced path name transformations for converting and renaming files and directories by applying prefixes, suffixes, and other alterations. For example: rclone convmv "stories/The Quick Brown Fox!.txt" --name-transform "all,uppercase" // Output: STORIES/THE QUICK BROWN FOX!.TXT See help doc for complete details.
This commit is contained in:
132
lib/transform/help.go
Normal file
132
lib/transform/help.go
Normal file
@@ -0,0 +1,132 @@
|
||||
package transform
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/rclone/rclone/fs"
|
||||
"github.com/rclone/rclone/lib/encoder"
|
||||
)
|
||||
|
||||
type commands struct {
|
||||
command string
|
||||
description string
|
||||
}
|
||||
|
||||
type example struct {
|
||||
path string
|
||||
flags []string
|
||||
}
|
||||
|
||||
var commandList = []commands{
|
||||
{command: "--name-transform prefix=XXXX", description: "Prepends XXXX to the file name."},
|
||||
{command: "--name-transform suffix=XXXX", description: "Appends XXXX to the file name after the extension."},
|
||||
{command: "--name-transform suffix_keep_extension=XXXX", description: "Appends XXXX to the file name while preserving the original file extension."},
|
||||
{command: "--name-transform trimprefix=XXXX", description: "Removes XXXX if it appears at the start of the file name."},
|
||||
{command: "--name-transform trimsuffix=XXXX", description: "Removes XXXX if it appears at the end of the file name."},
|
||||
{command: "--name-transform regex=/pattern/replacement/", description: "Applies a regex-based transformation."},
|
||||
{command: "--name-transform replace=old:new", description: "Replaces occurrences of old with new in the file name."},
|
||||
{command: "--name-transform date=YYYYMMDD", description: "Appends or prefixes the specified date format."},
|
||||
{command: "--name-transform truncate=N", description: "Truncates the file name to a maximum of N characters."},
|
||||
{command: "--name-transform base64encode", description: "Encodes the file name in Base64."},
|
||||
{command: "--name-transform base64decode", description: "Decodes a Base64-encoded file name."},
|
||||
{command: "--name-transform encoder=ENCODING", description: "Converts the file name to the specified encoding (e.g., ISO-8859-1, Windows-1252, Macintosh)."},
|
||||
{command: "--name-transform decoder=ENCODING", description: "Decodes the file name from the specified encoding."},
|
||||
{command: "--name-transform charmap=MAP", description: "Applies a character mapping transformation."},
|
||||
{command: "--name-transform lowercase", description: "Converts the file name to lowercase."},
|
||||
{command: "--name-transform uppercase", description: "Converts the file name to UPPERCASE."},
|
||||
{command: "--name-transform titlecase", description: "Converts the file name to Title Case."},
|
||||
{command: "--name-transform ascii", description: "Strips non-ASCII characters."},
|
||||
{command: "--name-transform url", description: "URL-encodes the file name."},
|
||||
{command: "--name-transform nfc", description: "Converts the file name to NFC Unicode normalization form."},
|
||||
{command: "--name-transform nfd", description: "Converts the file name to NFD Unicode normalization form."},
|
||||
{command: "--name-transform nfkc", description: "Converts the file name to NFKC Unicode normalization form."},
|
||||
{command: "--name-transform nfkd", description: "Converts the file name to NFKD Unicode normalization form."},
|
||||
{command: "--name-transform command=/path/to/my/programfile names.", description: "Executes an external program to transform"},
|
||||
}
|
||||
|
||||
var examples = []example{
|
||||
{"stories/The Quick Brown Fox!.txt", []string{"all,uppercase"}},
|
||||
{"stories/The Quick Brown Fox!.txt", []string{"all,replace=Fox:Turtle", "all,replace=Quick:Slow"}},
|
||||
{"stories/The Quick Brown Fox!.txt", []string{"all,base64encode"}},
|
||||
{"c3Rvcmllcw==/VGhlIFF1aWNrIEJyb3duIEZveCEudHh0", []string{"all,base64decode"}},
|
||||
{"stories/The Quick Brown 🦊 Fox Went to the Café!.txt", []string{"all,nfc"}},
|
||||
{"stories/The Quick Brown 🦊 Fox Went to the Café!.txt", []string{"all,nfd"}},
|
||||
{"stories/The Quick Brown 🦊 Fox!.txt", []string{"all,ascii"}},
|
||||
{"stories/The Quick Brown Fox!.txt", []string{"all,trimsuffix=.txt"}},
|
||||
{"stories/The Quick Brown Fox!.txt", []string{"all,prefix=OLD_"}},
|
||||
{"stories/The Quick Brown 🦊 Fox Went to the Café!.txt", []string{"all,charmap=ISO-8859-7"}},
|
||||
{"stories/The Quick Brown Fox: A Memoir [draft].txt", []string{"all,encoder=Colon,SquareBracket"}},
|
||||
{"stories/The Quick Brown 🦊 Fox Went to the Café!.txt", []string{"all,truncate=21"}},
|
||||
}
|
||||
|
||||
func (e example) command() string {
|
||||
s := fmt.Sprintf(`rclone convmv %q`, e.path)
|
||||
for _, f := range e.flags {
|
||||
s += fmt.Sprintf(" --name-transform %q", f)
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
func (e example) output() string {
|
||||
err := SetOptions(context.Background(), e.flags...)
|
||||
if err != nil {
|
||||
fs.Errorf(nil, "error generating help text: %v", err)
|
||||
}
|
||||
return Path(e.path, false)
|
||||
}
|
||||
|
||||
// go run ./ convmv --help
|
||||
func sprintExamples() string {
|
||||
s := "Examples: \n\n"
|
||||
for _, e := range examples {
|
||||
s += fmt.Sprintf("```\n%s\n", e.command())
|
||||
s += fmt.Sprintf("// Output: %s\n```\n\n", e.output())
|
||||
}
|
||||
Opt = Options{} // reset
|
||||
return s
|
||||
}
|
||||
|
||||
func commandTable() string {
|
||||
s := `| Command | Description |
|
||||
|------|------|`
|
||||
for _, c := range commandList {
|
||||
s += fmt.Sprintf("\n| `%s` | %s |", c.command, c.description)
|
||||
}
|
||||
s += "\n\n\n"
|
||||
return s
|
||||
}
|
||||
|
||||
// SprintList returns the example help text as a string
|
||||
func SprintList() string {
|
||||
var algos transformAlgo
|
||||
var charmaps fs.Enum[cmapChoices]
|
||||
s := commandTable()
|
||||
s += fmt.Sprintln("Conversion modes: \n```")
|
||||
for _, v := range algos.Choices() {
|
||||
s += fmt.Sprintln(v + " ")
|
||||
}
|
||||
s += fmt.Sprintln("```")
|
||||
|
||||
s += fmt.Sprintln("Char maps: \n```")
|
||||
for _, v := range charmaps.Choices() {
|
||||
s += fmt.Sprintln(v + " ")
|
||||
}
|
||||
s += fmt.Sprintln("```")
|
||||
|
||||
s += fmt.Sprintln("Encoding masks: \n```")
|
||||
for _, v := range strings.Split(encoder.ValidStrings(), ",") {
|
||||
s += fmt.Sprintln(v + " ")
|
||||
}
|
||||
s += fmt.Sprintln("```")
|
||||
|
||||
s += sprintExamples()
|
||||
|
||||
return s
|
||||
}
|
||||
|
||||
// PrintList prints the example help text to stdout
|
||||
func PrintList() {
|
||||
fmt.Println(SprintList())
|
||||
}
|
||||
@@ -47,7 +47,7 @@ const (
|
||||
var OptionsInfo = fs.Options{{
|
||||
Name: "name_transform",
|
||||
Default: []string{},
|
||||
Help: "TODO",
|
||||
Help: "`--name-transform` introduces path name transformations for `rclone copy`, `rclone sync`, and `rclone move`. These transformations enable modifications to source and destination file names by applying prefixes, suffixes, and other alterations during transfer operations. For detailed docs and examples, see [`convmv`](/commands/rclone_convmv/).",
|
||||
Groups: "Filter",
|
||||
}}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user