Implement the rclone cat command

This commit is contained in:
Nick Craig-Wood 2016-08-18 22:43:02 +01:00
parent f22029bf3d
commit 84eb7031bb
4 changed files with 90 additions and 0 deletions

View file

@ -5,6 +5,7 @@ import (
// Active commands
_ "github.com/ncw/rclone/cmd"
_ "github.com/ncw/rclone/cmd/authorize"
_ "github.com/ncw/rclone/cmd/cat"
_ "github.com/ncw/rclone/cmd/check"
_ "github.com/ncw/rclone/cmd/cleanup"
_ "github.com/ncw/rclone/cmd/config"

40
cmd/cat/cat.go Normal file
View file

@ -0,0 +1,40 @@
package cat
import (
"os"
"github.com/ncw/rclone/cmd"
"github.com/ncw/rclone/fs"
"github.com/spf13/cobra"
)
func init() {
cmd.Root.AddCommand(catCmd)
}
var catCmd = &cobra.Command{
Use: "cat remote:path",
Short: `Concatenates any files and sends them to stdout.`,
Long: `
rclone cat sends any files to standard output.
You can use it like this to output a single file
rclone cat remote:path/to/file
Or like this to output any file in dir or subdirectories.
rclone cat remote:path/to/dir
Or like this to output any .txt files in dir or subdirectories.
rclone --include "*.txt" cat remote:path/to/dir
`,
Run: func(command *cobra.Command, args []string) {
cmd.CheckArgs(1, 1, command, args)
fsrc := cmd.NewFsSrc(args)
cmd.Run(false, command, func() error {
return fs.Cat(fsrc, os.Stdout)
})
},
}

View file

@ -1012,3 +1012,34 @@ func CleanUp(f Fs) error {
}
return fc.CleanUp()
}
// Cat any files to the io.Writer
func Cat(f Fs, w io.Writer) error {
var mu sync.Mutex
return ListFn(f, func(o Object) {
Stats.Transferring(o.Remote())
defer Stats.DoneTransferring(o.Remote())
mu.Lock()
defer mu.Unlock()
in, err := o.Open()
if err != nil {
Stats.Error()
ErrorLog(o, "Failed to open: %v", err)
return
}
defer func() {
err = in.Close()
if err != nil {
Stats.Error()
ErrorLog(o, "Failed to close: %v", err)
}
}()
inAccounted := NewAccount(in, o) // account the transfer
_, err = io.Copy(w, inAccounted)
if err != nil {
Stats.Error()
ErrorLog(o, "Failed to send to output: %v", err)
}
})
}

View file

@ -620,3 +620,21 @@ func TestDeduplicateRename(t *testing.T) {
}
}
}
func TestCat(t *testing.T) {
r := NewRun(t)
defer r.Finalise()
file1 := r.WriteBoth("file1", "aaa", t1)
file2 := r.WriteBoth("file2", "bbb", t2)
fstest.CheckItems(t, r.fremote, file1, file2)
var buf bytes.Buffer
err := fs.Cat(r.fremote, &buf)
require.NoError(t, err)
res := buf.String()
if res != "aaabbb" && res != "bbbaaa" {
t.Errorf("Incorrect output from Cat: %q", res)
}
}