func (s *Action) binaryCopy(ctx context.Context, c *cli.Context, from, to string, deleteSource bool) error {
	if from == "" || to == "" {
		op := "copy"
		if deleteSource {
			op = "move"
		}
		return fmt.Errorf("usage: %s fs%s from to", c.App.Name, op)
	}
	switch {
	case fsutil.IsFile(from) && fsutil.IsFile(to):
		return fmt.Errorf("ambiguity detected. Only from or to can be a file")
	case s.Store.Exists(ctx, from) && s.Store.Exists(ctx, to):
		return fmt.Errorf("ambiguity detected. Either from or to must be a file")
	case fsutil.IsFile(from) && !fsutil.IsFile(to):
		return s.binaryCopyFromFileToStore(ctx, from, to, deleteSource)
	case !fsutil.IsFile(from):
		return s.binaryCopyFromStoreToFile(ctx, from, to, deleteSource)
	default:
		return fmt.Errorf("ambiguity detected. Unhandled case. Please report a bug")
	}
}
binaryCopy implements the control flow for copy and move. We support two
workflows:
1. From the filesystem to the store
2. From the store to the filesystem

Copying secrets in the store must be done through the regular copy command
package action
import (
	"bytes"
	"context"
	"crypto/sha256"
	"encoding/base64"
	"fmt"
	"io"
	"os"
	"path/filepath"
	"github.com/gopasspw/gopass/internal/out"
	"github.com/gopasspw/gopass/pkg/ctxutil"
	"github.com/gopasspw/gopass/pkg/debug"
	"github.com/gopasspw/gopass/pkg/fsutil"
	"github.com/gopasspw/gopass/pkg/gopass"
	"github.com/gopasspw/gopass/pkg/gopass/secrets"
	"github.com/urfave/cli/v2"
)
var (
	binstdin = os.Stdin
)
func (s *Action) Cat(c *cli.Context) error {
	ctx := ctxutil.WithGlobalFlags(c)
	name := c.Args().First()
	if name == "" {
		return ExitError(ExitNoName, nil, "Usage: %s cat <NAME>", c.App.Name)
	}
	info, err := binstdin.Stat()
	if err != nil {
		return ExitError(ExitIO, err, "failed to stat stdin: %s", err)
	}
	if info.Mode()&os.ModeCharDevice == 0 {
		debug.Log("Reading from STDIN ...")
		content := &bytes.Buffer{}
		if written, err := io.Copy(content, binstdin); err != nil {
			return ExitError(ExitIO, err, "Failed to copy after %d bytes: %s", written, err)
		}
		return s.Store.Set(
			ctxutil.WithCommitMessage(ctx, "Read secret from STDIN"),
			name,
			secFromBytes(name, "STDIN", content.Bytes()),
		)
	}
	buf, err := s.binaryGet(ctx, name)
	if err != nil {
		return ExitError(ExitDecrypt, err, "failed to read secret: %s", err)
	}
	fmt.Fprint(stdout, string(buf))
	return nil
}
func secFromBytes(dst, src string, in []byte) gopass.Secret {
	debug.Log("Read %d bytes from %s to %s", len(in), src, dst)
	sec := secrets.NewKV()
	if err := sec.Set("Content-Disposition", fmt.Sprintf("attachment; filename=\"%s\"", filepath.Base(src))); err != nil {
		debug.Log("Failed to set Content-Disposition: %q", err)
	}
	sec.Write([]byte(base64.StdEncoding.EncodeToString(in)))
	if err := sec.Set("Content-Transfer-Encoding", "Base64"); err != nil {
		debug.Log("Failed to set Content-Transfer-Encoding: %q", err)
	}
	return sec
}
func (s *Action) BinaryCopy(c *cli.Context) error {
	ctx := ctxutil.WithGlobalFlags(c)
	from := c.Args().Get(0)
	to := c.Args().Get(1)
	if err := s.binaryCopy(ctx, c, from, to, false); err != nil {
		return ExitError(ExitUnknown, err, "%s", err)
	}
	return nil
}
func (s *Action) BinaryMove(c *cli.Context) error {
	ctx := ctxutil.WithGlobalFlags(c)
	from := c.Args().Get(0)
	to := c.Args().Get(1)
	if err := s.binaryCopy(ctx, c, from, to, true); err != nil {
		return ExitError(ExitUnknown, err, "%s", err)
	}
	return nil
}