diff --git a/CHANGELOG.md b/CHANGELOG.md index 4232db1d4..973f35d4a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ #### Breaking changes - Dropped inline comment feature for `run` command. Previously s5cmd supported a command with an inline comment like `ls s3://bucket/object.gz # inline comment`. ([#309](https://github.com/peak/s5cmd/issues/309)) - Changed homebrew installation command on macOS. Users can install s5cmd via `brew install peak/tap/s5cmd`. ([#356](https://github.com/peak/s5cmd/issues/356)) +- Print usage errors to stderr instead of stdout and do not show help text on usage error. ([#399](https://github.com/peak/s5cmd/issues/399)) #### Features - Added `sync` command to synchronize two given buckets, prefixes, or objects. ([#3](https://github.com/peak/s5cmd/issues/3)) diff --git a/command/app.go b/command/app.go index 74ea2a14e..f10a759d2 100644 --- a/command/app.go +++ b/command/app.go @@ -3,6 +3,7 @@ package command import ( "context" "fmt" + "os" cmpinstall "github.com/posener/complete/cmd/install" "github.com/urfave/cli/v2" @@ -111,6 +112,15 @@ var app = &cli.App{ parallel.Close() log.Close() }, + OnUsageError: func(c *cli.Context, err error, isSubcommand bool) error { + if err != nil { + _, _ = fmt.Fprintf(os.Stderr, "%s %s\n", "Incorrect Usage:", err.Error()) + _, _ = fmt.Fprintf(os.Stderr, "See 's5cmd --help' for usage\n") + return err + } + + return nil + }, Action: func(c *cli.Context) error { if c.Bool("install-completion") { if cmpinstall.IsInstalled(appName) { diff --git a/e2e/app_test.go b/e2e/app_test.go index c68d7ce16..2b45a0cd2 100644 --- a/e2e/app_test.go +++ b/e2e/app_test.go @@ -101,3 +101,21 @@ func TestAppUnknownCommand(t *testing.T) { 0: equals(`ERROR "unknown-command": command not found`), }) } + +func TestUsageError(t *testing.T) { + t.Parallel() + + _, s5cmd, cleanup := setup(t) + defer cleanup() + + cmd := s5cmd("--recursive", "ls") + result := icmd.RunCmd(cmd) + + result.Assert(t, icmd.Expected{ExitCode: 1}) + + assertLines(t, result.Stdout(), map[int]compareFunc{}) + assertLines(t, result.Stderr(), map[int]compareFunc{ + 0: equals("Incorrect Usage: flag provided but not defined: -recursive"), + 1: equals("See 's5cmd --help' for usage"), + }) +}