mirror of
https://github.com/rclone/rclone.git
synced 2025-07-19 13:25:30 +02:00
107 lines
5.1 KiB
Go
107 lines
5.1 KiB
Go
// Package convmv provides the convmv command.
|
|
package convmv
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"strings"
|
|
|
|
"github.com/rclone/rclone/cmd"
|
|
"github.com/rclone/rclone/fs/config/flags"
|
|
"github.com/rclone/rclone/fs/operations"
|
|
"github.com/rclone/rclone/fs/sync"
|
|
"github.com/rclone/rclone/lib/transform"
|
|
"github.com/spf13/cobra"
|
|
)
|
|
|
|
// Globals
|
|
var (
|
|
deleteEmptySrcDirs = false
|
|
createEmptySrcDirs = false
|
|
)
|
|
|
|
func init() {
|
|
cmd.Root.AddCommand(commandDefinition)
|
|
cmdFlags := commandDefinition.Flags()
|
|
flags.BoolVarP(cmdFlags, &deleteEmptySrcDirs, "delete-empty-src-dirs", "", deleteEmptySrcDirs, "Delete empty source dirs after move", "")
|
|
flags.BoolVarP(cmdFlags, &createEmptySrcDirs, "create-empty-src-dirs", "", createEmptySrcDirs, "Create empty source dirs on destination after move", "")
|
|
}
|
|
|
|
var commandDefinition = &cobra.Command{
|
|
Use: "convmv dest:path --name-transform XXX",
|
|
Short: `Convert file and directory names in place.`,
|
|
// Warning¡ "¡" will be replaced by backticks below
|
|
Long: strings.ReplaceAll(`
|
|
convmv supports advanced path name transformations for converting and renaming files and directories by applying prefixes, suffixes, and other alterations.
|
|
|
|
`+transform.Help()+`Multiple transformations can be used in sequence, applied in the order they are specified on the command line.
|
|
|
|
The ¡--name-transform¡ flag is also available in ¡sync¡, ¡copy¡, and ¡move¡.
|
|
|
|
## Files vs Directories
|
|
|
|
By default ¡--name-transform¡ will only apply to file names. The means only the leaf file name will be transformed.
|
|
However some of the transforms would be better applied to the whole path or just directories.
|
|
To choose which which part of the file path is affected some tags can be added to the ¡--name-transform¡.
|
|
|
|
| Tag | Effect |
|
|
|------|------|
|
|
| ¡file¡ | Only transform the leaf name of files (DEFAULT) |
|
|
| ¡dir¡ | Only transform name of directories - these may appear anywhere in the path |
|
|
| ¡all¡ | Transform the entire path for files and directories |
|
|
|
|
This is used by adding the tag into the transform name like this: ¡--name-transform file,prefix=ABC¡ or ¡--name-transform dir,prefix=DEF¡.
|
|
|
|
For some conversions using all is more likely to be useful, for example ¡--name-transform all,nfc¡.
|
|
|
|
Note that ¡--name-transform¡ may not add path separators ¡/¡ to the name. This will cause an error.
|
|
|
|
## Ordering and Conflicts
|
|
|
|
* Transformations will be applied in the order specified by the user.
|
|
* If the ¡file¡ tag is in use (the default) then only the leaf name of files will be transformed.
|
|
* If the ¡dir¡ tag is in use then directories anywhere in the path will be transformed
|
|
* If the ¡all¡ tag is in use then directories and files anywhere in the path will be transformed
|
|
* Each transformation will be run one path segment at a time.
|
|
* If a transformation adds a ¡/¡ or ends up with an empty path segment then that will be an error.
|
|
* It is up to the user to put the transformations in a sensible order.
|
|
* Conflicting transformations, such as ¡prefix¡ followed by ¡trimprefix¡ or ¡nfc¡ followed by ¡nfd¡, are possible.
|
|
* Instead of enforcing mutual exclusivity, transformations are applied in sequence as specified by the
|
|
user, allowing for intentional use cases (e.g., trimming one prefix before adding another).
|
|
* Users should be aware that certain combinations may lead to unexpected results and should verify
|
|
transformations using ¡--dry-run¡ before execution.
|
|
|
|
## Race Conditions and Non-Deterministic Behavior
|
|
|
|
Some transformations, such as ¡replace=old:new¡, may introduce conflicts where multiple source files map to the same destination name.
|
|
This can lead to race conditions when performing concurrent transfers. It is up to the user to anticipate these.
|
|
* If two files from the source are transformed into the same name at the destination, the final state may be non-deterministic.
|
|
* Running rclone check after a sync using such transformations may erroneously report missing or differing files due to overwritten results.
|
|
|
|
To minimize risks, users should:
|
|
* Carefully review transformations that may introduce conflicts.
|
|
* Use ¡--dry-run¡ to inspect changes before executing a sync (but keep in mind that it won't show the effect of non-deterministic transformations).
|
|
* Avoid transformations that cause multiple distinct source files to map to the same destination name.
|
|
* Consider disabling concurrency with ¡--transfers=1¡ if necessary.
|
|
* Certain transformations (e.g. ¡prefix¡) will have a multiplying effect every time they are used. Avoid these when using ¡bisync¡.
|
|
|
|
`, "¡", "`"),
|
|
Annotations: map[string]string{
|
|
"versionIntroduced": "v1.70",
|
|
"groups": "Filter,Listing,Important,Copy",
|
|
},
|
|
Run: func(command *cobra.Command, args []string) {
|
|
cmd.CheckArgs(1, 1, command, args)
|
|
fdst, srcFileName := cmd.NewFsFile(args[0])
|
|
cmd.Run(false, true, command, func() error {
|
|
if !transform.Transforming(context.Background()) {
|
|
return errors.New("--name-transform must be set")
|
|
}
|
|
if srcFileName == "" {
|
|
return sync.Transform(context.Background(), fdst, deleteEmptySrcDirs, createEmptySrcDirs)
|
|
}
|
|
return operations.TransformFile(context.Background(), fdst, srcFileName)
|
|
})
|
|
},
|
|
}
|