Skip to content

Commit

Permalink
add Exiftool configuration options
Browse files Browse the repository at this point in the history
  • Loading branch information
ayoisaiah committed Apr 26, 2024
1 parent e94e683 commit 194effd
Show file tree
Hide file tree
Showing 9 changed files with 174 additions and 5 deletions.
8 changes: 6 additions & 2 deletions app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ const (
// supportedDefaultOptions contains those flags that can be
// overridden through the `F2_DEFAULT_OPTS` environmental variable.
var supportedDefaultOptions = []string{
"hidden", "allow-overwrites", "exclude", "exec", "fix-conflicts", "include-dir", "ignore-case", "ignore-ext", "interactive", "json", "max-depth", "no-color", "only-dir", "quiet", "recursive", "replace-limit", "sort", "sortr", "string-mode", "verbose",
"hidden", "allow-overwrites", "exclude", "exec", "fix-conflicts", "include-dir", "ignore-case", "ignore-ext", "interactive", "json", "max-depth", "no-color", "only-dir", "quiet", "recursive", "replace-limit", "sort", "sortr", "string-mode", "verbose", "exiftool-opts",
}

func init() {
Expand Down Expand Up @@ -85,7 +85,7 @@ func getDefaultOptsCtx() *cli.Context {
}

// Run needs to be called here so that `defaultCtx` is populated
// It errors out when
// It errors out when // TODO: complete this
err := app.Run(defaultOpts)
if err != nil {
// TODO: Decide what to do here
Expand Down Expand Up @@ -231,6 +231,10 @@ or: FIND [REPLACE] [PATHS TO FILES AND DIRECTORIES...]`
DefaultText: "<path/to/csv/file>",
TakesFile: true,
},
&cli.StringFlag{
Name: "exiftool-opts",
Usage: "Provide custom options when using ExifTool variables",
},
&cli.StringSliceFlag{
Name: "find",
Aliases: []string{"f"},
Expand Down
5 changes: 3 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@ go 1.21

require (
github.com/adrg/xdg v0.4.0
github.com/barasher/go-exiftool v1.8.0
github.com/barasher/go-exiftool v1.10.0
github.com/dhowden/tag v0.0.0-20220618230019-adf36e896086
github.com/google/go-cmp v0.5.9
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51
github.com/pterm/pterm v0.12.46
github.com/rwcarlsen/goexif v0.0.0-20190401172101-9e8deecbddbd
github.com/urfave/cli/v2 v2.4.10
golang.org/x/sys v0.16.0 // indirect
golang.org/x/sys v0.19.0 // indirect
golang.org/x/text v0.3.7
gopkg.in/djherbis/times.v1 v1.3.0
)
Expand All @@ -32,6 +32,7 @@ require (
github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect
github.com/djherbis/times v1.6.0 // indirect
github.com/gookit/color v1.5.2 // indirect
github.com/jessevdk/go-flags v1.5.0 // indirect
github.com/lithammer/fuzzysearch v1.1.5 // indirect
github.com/mattn/go-runewidth v0.0.13 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
Expand Down
7 changes: 7 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ github.com/araddon/dateparse v0.0.0-20210429162001-6b43995a97de/go.mod h1:DCaWoU
github.com/atomicgo/cursor v0.0.1/go.mod h1:cBON2QmmrysudxNBFthvMtN32r3jxVRIvzkUiF/RuIk=
github.com/barasher/go-exiftool v1.8.0 h1:u8bEi1mhLtpVC5aG/ZJlRS/r+SkK+rcgbZQwcKUb424=
github.com/barasher/go-exiftool v1.8.0/go.mod h1:F9s/a3uHSM8YniVfwF+sbQUtP8Gmh9nyzigNF+8vsWo=
github.com/barasher/go-exiftool v1.10.0 h1:f5JY5jc42M7tzR6tbL9508S2IXdIcG9QyieEXNMpIhs=
github.com/barasher/go-exiftool v1.10.0/go.mod h1:F9s/a3uHSM8YniVfwF+sbQUtP8Gmh9nyzigNF+8vsWo=
github.com/containerd/console v1.0.3 h1:lIr7SlA5PxZyMV30bDW0MGbiOPXwc63yRuCP0ARubLw=
github.com/containerd/console v1.0.3/go.mod h1:7LqA/THxQ86k76b8c/EMSiaJ3h1eZkMkXar0TQ1gf3U=
github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w=
Expand All @@ -36,6 +38,8 @@ github.com/gookit/color v1.4.2/go.mod h1:fqRyamkC1W8uxl+lxCQxOT09l/vYfZ+QeiX3rKQ
github.com/gookit/color v1.5.0/go.mod h1:43aQb+Zerm/BWh2GnrgOQm7ffz7tvQXEKV6BFMl7wAo=
github.com/gookit/color v1.5.2 h1:uLnfXcaFjlrDnQDT+NCBcfhrXqYTx/rcCa6xn01Y8yI=
github.com/gookit/color v1.5.2/go.mod h1:w8h4bGiHeeBpvQVePTutdbERIUf3oJE5lZ8HM0UgXyg=
github.com/jessevdk/go-flags v1.5.0 h1:1jKYvbxEjfUl0fmqTCOfonvskHHXMjBySTLW4y9LFvc=
github.com/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c2EWnYs/m4=
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs=
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8=
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
Expand Down Expand Up @@ -99,6 +103,7 @@ golang.org/x/exp v0.0.0-20221028150844-83b7d23a625f h1:Al51T6tzvuh3oiwX11vex3QgJ
golang.org/x/exp v0.0.0-20221028150844-83b7d23a625f/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211013075003-97ac67df715c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
Expand All @@ -109,6 +114,8 @@ golang.org/x/sys v0.1.0 h1:kunALQeHf1/185U1i0GOB/fy1IPRDDpuoOOqRReG57U=
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU=
golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o=
golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
Expand Down
24 changes: 24 additions & 0 deletions internal/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ import (
"strings"
"time"

"github.com/jessevdk/go-flags"
"github.com/kballard/go-shellquote"
"github.com/urfave/cli/v2"
)

Expand All @@ -26,6 +28,15 @@ var (

var conf *Config

// ExiftoolOpts defines supported options for customizing Exitool's output
type ExiftoolOpts struct {
API string `long:"api"` // corresponds to the `-api` flag
Charset string `long:"charset"` // corresponds to the `-charset` flag
CoordFormat string `long:"coordFormat"` // corresponds to the `-coordFormat` flag
DateFormat string `long:"dateFormat"` // corresponds to the `-dateFormat` flag
ExtractEmbedded bool `long:"extractEmbedded"` // corresponds to the `-extractEmbedded` flag
}

// Config represents the program configuration.
type Config struct {
Date time.Time
Expand Down Expand Up @@ -62,6 +73,7 @@ type Config struct {
SimpleMode bool
JSON bool
Interactive bool
ExiftoolOpts ExiftoolOpts
}

// SetFindStringRegex compiles a regular expression for the
Expand Down Expand Up @@ -109,6 +121,18 @@ func (c *Config) setOptions(ctx *cli.Context) error {
c.Revert = ctx.Bool("undo")
c.FilesAndDirPaths = ctx.Args().Slice()

if len(ctx.String("exiftool-opts")) != 0 {
args, err := shellquote.Split(ctx.String("exiftool-opts"))
if err != nil {
return err
}

_, err = flags.ParseArgs(&c.ExiftoolOpts, args)
if err != nil {
return err
}
}

// Default to the current working directory if no path arguments are provided
if len(c.FilesAndDirPaths) == 0 {
c.FilesAndDirPaths = append(c.FilesAndDirPaths, ".")
Expand Down
Binary file added replace/replace_test/testdata/binary.mp3
Binary file not shown.
Binary file added replace/replace_test/testdata/embedded.mp4
Binary file not shown.
Binary file added replace/replace_test/testdata/gps.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
105 changes: 105 additions & 0 deletions replace/replace_test/variables_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,111 @@ func TestVariables(t *testing.T) {
"{btime.YYYY}-{ctime.MM}-{now.DD}{ext}",
},
},
{
Name: "replace GPSPosition Exiftool tag using default settings",
Changes: []*file.Change{
{
BaseDir: "testdata",
Source: "gps.jpg",
},
},
Want: []string{
`testdata/43 deg 28' 2.81" N, 11 deg 53' 6.46" E.jpg`,
},
Args: []string{
"-r", "{xt.GPSPosition}{ext}",
},
},
{
Name: "use --coordFormat Exiftool option to customize GPS format",
Changes: []*file.Change{
{
BaseDir: "testdata",
Source: "gps.jpg",
},
},
Want: []string{
"testdata/+43.467448, +11.885127.jpg",
},
Args: []string{
"-r", "{xt.GPSPosition}{ext}", "--exiftool-opts", `--coordFormat %+f`,
},
},
{
Name: "use Exiftool GPSDateTime tag default format",
Changes: []*file.Change{
{
BaseDir: "testdata",
Source: "gps.jpg",
},
},
Want: []string{
"testdata/2008:10:23 14:27:07.24Z.jpg",
},
Args: []string{
"-r", "{xt.GPSDateTime}{ext}",
},
},
{
Name: "use --dateFormat Exiftool option to customize date format",
Changes: []*file.Change{
{
BaseDir: "testdata",
Source: "gps.jpg",
},
},
Want: []string{
"testdata/2008-10-23.jpg",
},
Args: []string{
"-r", "{xt.GPSDateTime}{ext}", "--exiftool-opts", `--dateFormat %Y-%m-%d`,
},
},
{
Name: "use --api Exiftool option to customize date format",
Changes: []*file.Change{
{
BaseDir: "testdata",
Source: "gps.jpg",
},
},
Want: []string{
"testdata/2008-10-23.jpg",
},
Args: []string{
"-r", "{xt.GPSDateTime}{ext}", "--exiftool-opts", `--api DateFormat=%Y-%m-%d`,
},
},
{
Name: "fail to find OtherSerialNumber tag without --extractEmbedded Exiftool option",
Changes: []*file.Change{
{
BaseDir: "testdata",
Source: "embedded.mp4",
},
},
Want: []string{
"testdata/.mp4",
},
Args: []string{
"-r", "{xt.OtherSerialNumber}{ext}",
},
},
{
Name: "find OtherSerialNumber tag with --extractEmbedded Exiftool option",
Changes: []*file.Change{
{
BaseDir: "testdata",
Source: "embedded.mp4",
},
},
Want: []string{
"testdata/HERO4 Silver.mp4",
},
Args: []string{
"-r", "{xt.OtherSerialNumber}{ext}", "--exiftool-opts", `--extractEmbedded`,
},
},
}

replaceTest(t, testCases)
Expand Down
30 changes: 29 additions & 1 deletion replace/variables.go
Original file line number Diff line number Diff line change
Expand Up @@ -611,7 +611,34 @@ func replaceExifToolVars(
target, sourcePath string,
xtVars exiftoolVars,
) (string, error) {
et, err := exiftool.NewExiftool()
conf := config.Get()

var opts []func(*exiftool.Exiftool) error

if conf.ExiftoolOpts.API != "" {
opts = append(opts, exiftool.Api(conf.ExiftoolOpts.API))
}

if conf.ExiftoolOpts.Charset != "" {
opts = append(opts, exiftool.Charset(conf.ExiftoolOpts.Charset))
}

if conf.ExiftoolOpts.CoordFormat != "" {
opts = append(
opts,
exiftool.CoordFormant(conf.ExiftoolOpts.CoordFormat),
)
}

if conf.ExiftoolOpts.DateFormat != "" {
opts = append(opts, exiftool.DateFormant(conf.ExiftoolOpts.DateFormat))
}

if conf.ExiftoolOpts.ExtractEmbedded {
opts = append(opts, exiftool.ExtractEmbedded())
}

et, err := exiftool.NewExiftool(opts...)
if err != nil {
return "", fmt.Errorf("Failed to initialise exiftool: %w", err)
}
Expand All @@ -634,6 +661,7 @@ func replaceExifToolVars(
if current.attr == k {
value = fmt.Sprintf("%v", v)
// replace forward and backward slashes with underscore
// TODO: Make this configurable?
value = strings.ReplaceAll(value, `/`, "_")
value = strings.ReplaceAll(value, `\`, "_")

Expand Down

0 comments on commit 194effd

Please sign in to comment.