mirror of
https://github.com/rclone/rclone.git
synced 2025-03-30 09:56:19 +02:00
Implement the rclone cat command
This commit is contained in:
parent
f22029bf3d
commit
84eb7031bb
@ -5,6 +5,7 @@ import (
|
|||||||
// Active commands
|
// Active commands
|
||||||
_ "github.com/ncw/rclone/cmd"
|
_ "github.com/ncw/rclone/cmd"
|
||||||
_ "github.com/ncw/rclone/cmd/authorize"
|
_ "github.com/ncw/rclone/cmd/authorize"
|
||||||
|
_ "github.com/ncw/rclone/cmd/cat"
|
||||||
_ "github.com/ncw/rclone/cmd/check"
|
_ "github.com/ncw/rclone/cmd/check"
|
||||||
_ "github.com/ncw/rclone/cmd/cleanup"
|
_ "github.com/ncw/rclone/cmd/cleanup"
|
||||||
_ "github.com/ncw/rclone/cmd/config"
|
_ "github.com/ncw/rclone/cmd/config"
|
||||||
|
40
cmd/cat/cat.go
Normal file
40
cmd/cat/cat.go
Normal 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)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
}
|
@ -1012,3 +1012,34 @@ func CleanUp(f Fs) error {
|
|||||||
}
|
}
|
||||||
return fc.CleanUp()
|
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)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
}
|
||||||
|
@ -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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user