mirror of https://github.com/rclone/rclone.git
cat: adds --separator option to cat command
When using `rclone cat` to print the contents of several files, the user may want to inject some separator between the files, such as a comma or a newline. This patch adds a `--separator` option to the `cat` command to make that possible. The default value remains an empty string, `""`, maintaining the prior behavior of `rclone cat`. Closes #6968
This commit is contained in:
parent
db8c007983
commit
3e15a594b7
|
@ -824,8 +824,9 @@ func touchFiles(ctx context.Context, dateStr string, f fs.Fs, dir, glob string)
|
||||||
err = nil
|
err = nil
|
||||||
buf := new(bytes.Buffer)
|
buf := new(bytes.Buffer)
|
||||||
size := obj.Size()
|
size := obj.Size()
|
||||||
|
separator := ""
|
||||||
if size > 0 {
|
if size > 0 {
|
||||||
err = operations.Cat(ctx, f, buf, 0, size)
|
err = operations.Cat(ctx, f, buf, 0, size, []byte(separator))
|
||||||
}
|
}
|
||||||
info := object.NewStaticObjectInfo(remote, date, size, true, nil, f)
|
info := object.NewStaticObjectInfo(remote, date, size, true, nil, f)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
|
|
|
@ -21,6 +21,7 @@ var (
|
||||||
offset = int64(0)
|
offset = int64(0)
|
||||||
count = int64(-1)
|
count = int64(-1)
|
||||||
discard = false
|
discard = false
|
||||||
|
separator = string("")
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
@ -31,6 +32,7 @@ func init() {
|
||||||
flags.Int64VarP(cmdFlags, &offset, "offset", "", offset, "Start printing at offset N (or from end if -ve)")
|
flags.Int64VarP(cmdFlags, &offset, "offset", "", offset, "Start printing at offset N (or from end if -ve)")
|
||||||
flags.Int64VarP(cmdFlags, &count, "count", "", count, "Only print N characters")
|
flags.Int64VarP(cmdFlags, &count, "count", "", count, "Only print N characters")
|
||||||
flags.BoolVarP(cmdFlags, &discard, "discard", "", discard, "Discard the output instead of printing")
|
flags.BoolVarP(cmdFlags, &discard, "discard", "", discard, "Discard the output instead of printing")
|
||||||
|
flags.StringVarP(cmdFlags, &separator, "separator", "", separator, "Separator to use between objects when printing multiple files")
|
||||||
}
|
}
|
||||||
|
|
||||||
var commandDefinition = &cobra.Command{
|
var commandDefinition = &cobra.Command{
|
||||||
|
@ -56,6 +58,18 @@ Use the |--head| flag to print characters only at the start, |--tail| for
|
||||||
the end and |--offset| and |--count| to print a section in the middle.
|
the end and |--offset| and |--count| to print a section in the middle.
|
||||||
Note that if offset is negative it will count from the end, so
|
Note that if offset is negative it will count from the end, so
|
||||||
|--offset -1 --count 1| is equivalent to |--tail 1|.
|
|--offset -1 --count 1| is equivalent to |--tail 1|.
|
||||||
|
|
||||||
|
Use the |--separator| flag to print a separator value between files. Be sure to
|
||||||
|
shell-escape special characters. For example, to print a newline between
|
||||||
|
files, use:
|
||||||
|
|
||||||
|
* bash:
|
||||||
|
|
||||||
|
rclone --include "*.txt" --separator $'\n' cat remote:path/to/dir
|
||||||
|
|
||||||
|
* powershell:
|
||||||
|
|
||||||
|
rclone --include "*.txt" --separator "|n" cat remote:path/to/dir
|
||||||
`, "|", "`"),
|
`, "|", "`"),
|
||||||
Annotations: map[string]string{
|
Annotations: map[string]string{
|
||||||
"versionIntroduced": "v1.33",
|
"versionIntroduced": "v1.33",
|
||||||
|
@ -82,7 +96,7 @@ Note that if offset is negative it will count from the end, so
|
||||||
w = io.Discard
|
w = io.Discard
|
||||||
}
|
}
|
||||||
cmd.Run(false, false, command, func() error {
|
cmd.Run(false, false, command, func() error {
|
||||||
return operations.Cat(context.Background(), fsrc, w, offset, count)
|
return operations.Cat(context.Background(), fsrc, w, offset, count, []byte(separator))
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,6 +32,18 @@ the end and `--offset` and `--count` to print a section in the middle.
|
||||||
Note that if offset is negative it will count from the end, so
|
Note that if offset is negative it will count from the end, so
|
||||||
`--offset -1 --count 1` is equivalent to `--tail 1`.
|
`--offset -1 --count 1` is equivalent to `--tail 1`.
|
||||||
|
|
||||||
|
Use the `--separator` flag to print a separator value between files. Be sure to
|
||||||
|
shell-escape special characters. For example, to print a newline between
|
||||||
|
files, use:
|
||||||
|
|
||||||
|
* bash:
|
||||||
|
|
||||||
|
rclone --include "*.txt" --separator $'\n' cat remote:path/to/dir
|
||||||
|
|
||||||
|
* powershell:
|
||||||
|
|
||||||
|
rclone --include "*.txt" --separator "`n" cat remote:path/to/dir
|
||||||
|
|
||||||
|
|
||||||
```
|
```
|
||||||
rclone cat remote:path [flags]
|
rclone cat remote:path [flags]
|
||||||
|
@ -45,6 +57,7 @@ rclone cat remote:path [flags]
|
||||||
--head int Only print the first N characters
|
--head int Only print the first N characters
|
||||||
-h, --help help for cat
|
-h, --help help for cat
|
||||||
--offset int Start printing at offset N (or from end if -ve)
|
--offset int Start printing at offset N (or from end if -ve)
|
||||||
|
--separator string Separator to use between objects when printing multiple files
|
||||||
--tail int Only print the last N characters
|
--tail int Only print the last N characters
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
@ -1259,7 +1259,7 @@ type readCloser struct {
|
||||||
//
|
//
|
||||||
// if count < 0 then it will be ignored
|
// if count < 0 then it will be ignored
|
||||||
// if count >= 0 then only that many characters will be output
|
// if count >= 0 then only that many characters will be output
|
||||||
func Cat(ctx context.Context, f fs.Fs, w io.Writer, offset, count int64) error {
|
func Cat(ctx context.Context, f fs.Fs, w io.Writer, offset, count int64, sep []byte) error {
|
||||||
var mu sync.Mutex
|
var mu sync.Mutex
|
||||||
ci := fs.GetConfig(ctx)
|
ci := fs.GetConfig(ctx)
|
||||||
return ListFn(ctx, f, func(o fs.Object) {
|
return ListFn(ctx, f, func(o fs.Object) {
|
||||||
|
@ -1301,6 +1301,13 @@ func Cat(ctx context.Context, f fs.Fs, w io.Writer, offset, count int64) error {
|
||||||
err = fs.CountError(err)
|
err = fs.CountError(err)
|
||||||
fs.Errorf(o, "Failed to send to output: %v", err)
|
fs.Errorf(o, "Failed to send to output: %v", err)
|
||||||
}
|
}
|
||||||
|
if len(sep) >= 0 {
|
||||||
|
_, err = w.Write(sep)
|
||||||
|
if err != nil {
|
||||||
|
err = fs.CountError(err)
|
||||||
|
fs.Errorf(o, "Failed to send separator to output: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -531,21 +531,23 @@ func TestCat(t *testing.T) {
|
||||||
for _, test := range []struct {
|
for _, test := range []struct {
|
||||||
offset int64
|
offset int64
|
||||||
count int64
|
count int64
|
||||||
|
separator string
|
||||||
a string
|
a string
|
||||||
b string
|
b string
|
||||||
}{
|
}{
|
||||||
{0, -1, "ABCDEFGHIJ", "012345678"},
|
{0, -1, "", "ABCDEFGHIJ", "012345678"},
|
||||||
{0, 5, "ABCDE", "01234"},
|
{0, 5, "", "ABCDE", "01234"},
|
||||||
{-3, -1, "HIJ", "678"},
|
{-3, -1, "", "HIJ", "678"},
|
||||||
{1, 3, "BCD", "123"},
|
{1, 3, "", "BCD", "123"},
|
||||||
|
{0, -1, "\n", "ABCDEFGHIJ", "012345678"},
|
||||||
} {
|
} {
|
||||||
var buf bytes.Buffer
|
var buf bytes.Buffer
|
||||||
err := operations.Cat(ctx, r.Fremote, &buf, test.offset, test.count)
|
err := operations.Cat(ctx, r.Fremote, &buf, test.offset, test.count, []byte(test.separator))
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
res := buf.String()
|
res := buf.String()
|
||||||
|
|
||||||
if res != test.a+test.b && res != test.b+test.a {
|
if res != test.a+test.separator+test.b+test.separator && res != test.b+test.separator+test.a+test.separator {
|
||||||
t.Errorf("Incorrect output from Cat(%d,%d): %q", test.offset, test.count, res)
|
t.Errorf("Incorrect output from Cat(%d,%d,%s): %q", test.offset, test.count, test.separator, res)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue