diff --git a/docs/src/keystroke-savers.md b/docs/src/keystroke-savers.md index ec15e9308..e8fbc9073 100644 --- a/docs/src/keystroke-savers.md +++ b/docs/src/keystroke-savers.md @@ -57,6 +57,208 @@ red square true 2 15 79.2778 0.0130 You can get the full list [here](file-formats.md#data-conversion-keystroke-savers). +## Omitting the verb for format conversions + +The verb defaults to [`cat`](reference-verbs.md#cat), so for pure format conversions you can leave the verb off entirely: + +
+mlr --c2j cat example.csv ++
+[
+{
+ "color": "yellow",
+ "shape": "triangle",
+ "flag": "true",
+ "k": 1,
+ "index": 11,
+ "quantity": 43.6498,
+ "rate": 9.8870
+},
+{
+ "color": "red",
+ "shape": "square",
+ "flag": "true",
+ "k": 2,
+ "index": 15,
+ "quantity": 79.2778,
+ "rate": 0.0130
+},
+{
+ "color": "red",
+ "shape": "circle",
+ "flag": "true",
+ "k": 3,
+ "index": 16,
+ "quantity": 13.8103,
+ "rate": 2.9010
+},
+{
+ "color": "red",
+ "shape": "square",
+ "flag": "false",
+ "k": 4,
+ "index": 48,
+ "quantity": 77.5542,
+ "rate": 7.4670
+},
+{
+ "color": "purple",
+ "shape": "triangle",
+ "flag": "false",
+ "k": 5,
+ "index": 51,
+ "quantity": 81.2290,
+ "rate": 8.5910
+},
+{
+ "color": "red",
+ "shape": "square",
+ "flag": "false",
+ "k": 6,
+ "index": 64,
+ "quantity": 77.1991,
+ "rate": 9.5310
+},
+{
+ "color": "purple",
+ "shape": "triangle",
+ "flag": "false",
+ "k": 7,
+ "index": 65,
+ "quantity": 80.1405,
+ "rate": 5.8240
+},
+{
+ "color": "yellow",
+ "shape": "circle",
+ "flag": "true",
+ "k": 8,
+ "index": 73,
+ "quantity": 63.9785,
+ "rate": 4.2370
+},
+{
+ "color": "yellow",
+ "shape": "circle",
+ "flag": "true",
+ "k": 9,
+ "index": 87,
+ "quantity": 63.5058,
+ "rate": 8.3350
+},
+{
+ "color": "purple",
+ "shape": "square",
+ "flag": "false",
+ "k": 10,
+ "index": 91,
+ "quantity": 72.3735,
+ "rate": 8.2430
+}
+]
+
+
++mlr --c2j --from example.csv ++
+[
+{
+ "color": "yellow",
+ "shape": "triangle",
+ "flag": "true",
+ "k": 1,
+ "index": 11,
+ "quantity": 43.6498,
+ "rate": 9.8870
+},
+{
+ "color": "red",
+ "shape": "square",
+ "flag": "true",
+ "k": 2,
+ "index": 15,
+ "quantity": 79.2778,
+ "rate": 0.0130
+},
+{
+ "color": "red",
+ "shape": "circle",
+ "flag": "true",
+ "k": 3,
+ "index": 16,
+ "quantity": 13.8103,
+ "rate": 2.9010
+},
+{
+ "color": "red",
+ "shape": "square",
+ "flag": "false",
+ "k": 4,
+ "index": 48,
+ "quantity": 77.5542,
+ "rate": 7.4670
+},
+{
+ "color": "purple",
+ "shape": "triangle",
+ "flag": "false",
+ "k": 5,
+ "index": 51,
+ "quantity": 81.2290,
+ "rate": 8.5910
+},
+{
+ "color": "red",
+ "shape": "square",
+ "flag": "false",
+ "k": 6,
+ "index": 64,
+ "quantity": 77.1991,
+ "rate": 9.5310
+},
+{
+ "color": "purple",
+ "shape": "triangle",
+ "flag": "false",
+ "k": 7,
+ "index": 65,
+ "quantity": 80.1405,
+ "rate": 5.8240
+},
+{
+ "color": "yellow",
+ "shape": "circle",
+ "flag": "true",
+ "k": 8,
+ "index": 73,
+ "quantity": 63.9785,
+ "rate": 4.2370
+},
+{
+ "color": "yellow",
+ "shape": "circle",
+ "flag": "true",
+ "k": 9,
+ "index": 87,
+ "quantity": 63.5058,
+ "rate": 8.3350
+},
+{
+ "color": "purple",
+ "shape": "square",
+ "flag": "false",
+ "k": 10,
+ "index": 91,
+ "quantity": 72.3735,
+ "rate": 8.2430
+}
+]
+
+
+The second form is equivalent to `mlr --c2j cat example.csv`. Piped stdin works the same way: `cat example.csv | mlr --c2j`.
+
## File names up front, including --from
Already, we saw that you can put the filename first using `--from`. When you're interacting with your data at the command line, this makes it easier to up-arrow and append to the previous command:
diff --git a/docs/src/keystroke-savers.md.in b/docs/src/keystroke-savers.md.in
index 648c63fc7..b39a6affc 100644
--- a/docs/src/keystroke-savers.md.in
+++ b/docs/src/keystroke-savers.md.in
@@ -14,6 +14,20 @@ GENMD-EOF
You can get the full list [here](file-formats.md#data-conversion-keystroke-savers).
+## Omitting the verb for format conversions
+
+The verb defaults to [`cat`](reference-verbs.md#cat), so for pure format conversions you can leave the verb off entirely:
+
+GENMD-RUN-COMMAND
+mlr --c2j cat example.csv
+GENMD-EOF
+
+GENMD-RUN-COMMAND
+mlr --c2j --from example.csv
+GENMD-EOF
+
+The second form is equivalent to `mlr --c2j cat example.csv`. Piped stdin works the same way: `cat example.csv | mlr --c2j`.
+
## File names up front, including --from
Already, we saw that you can put the filename first using `--from`. When you're interacting with your data at the command line, this makes it easier to up-arrow and append to the previous command:
diff --git a/docs/src/manpage.md b/docs/src/manpage.md
index 8a4de9a56..71f87da1b 100644
--- a/docs/src/manpage.md
+++ b/docs/src/manpage.md
@@ -26,9 +26,13 @@ This is simply a copy of what you should see on running `man mlr` at a command p
as CSV and tabular JSON.
1mSYNOPSIS0m
- Usage: mlr [flags] {verb} [verb-dependent options ...] {zero or more
+ Usage: mlr [flags] [verb] [verb-dependent options ...] {zero or more
file names}
+ If no verb is given, "cat" is used, which is handy for format
+ conversions, e.g.
+ mlr --c2j < example.csv
+
If zero file names are provided, standard input is read, e.g.
mlr --csv sort -f shape example.csv
@@ -3846,5 +3850,5 @@ This is simply a copy of what you should see on running `man mlr` at a command p
MIME Type for Comma-Separated Values (CSV) Files, the Miller docsite
https://miller.readthedocs.io
- 2026-05-16 4mMILLER24m(1)
+ 2026-05-17 4mMILLER24m(1)
diff --git a/docs/src/manpage.txt b/docs/src/manpage.txt
index c505c8ee4..e55be814b 100644
--- a/docs/src/manpage.txt
+++ b/docs/src/manpage.txt
@@ -5,9 +5,13 @@
as CSV and tabular JSON.
1mSYNOPSIS0m
- Usage: mlr [flags] {verb} [verb-dependent options ...] {zero or more
+ Usage: mlr [flags] [verb] [verb-dependent options ...] {zero or more
file names}
+ If no verb is given, "cat" is used, which is handy for format
+ conversions, e.g.
+ mlr --c2j < example.csv
+
If zero file names are provided, standard input is read, e.g.
mlr --csv sort -f shape example.csv
@@ -3825,4 +3829,4 @@
MIME Type for Comma-Separated Values (CSV) Files, the Miller docsite
https://miller.readthedocs.io
- 2026-05-16 4mMILLER24m(1)
+ 2026-05-17 4mMILLER24m(1)
diff --git a/docs/src/online-help.md b/docs/src/online-help.md
index f112b1e18..9571696d5 100644
--- a/docs/src/online-help.md
+++ b/docs/src/online-help.md
@@ -26,7 +26,10 @@ The front door is `mlr --help` or its synonym `mlr -h`. This leads you to `mlr h
mlr --help
-Usage: mlr [flags] {verb} [verb-dependent options ...] {zero or more file names}
+Usage: mlr [flags] [verb] [verb-dependent options ...] {zero or more file names}
+
+If no verb is given, "cat" is used, which is handy for format conversions, e.g.
+ mlr --c2j < example.csv
If zero file names are provided, standard input is read, e.g.
mlr --csv sort -f shape example.csv
diff --git a/docs/src/reference-main-overview.md b/docs/src/reference-main-overview.md
index b7e1a97c4..de241cf5f 100644
--- a/docs/src/reference-main-overview.md
+++ b/docs/src/reference-main-overview.md
@@ -66,6 +66,8 @@ See also the [Glossary](glossary.md) for more about terms such as
When you type `mlr {something} myfile.dat`, the `{something}` part is called a **verb**. It specifies how you want to transform your data. Most of the verbs are counterparts of built-in system tools like `cut` and `sort` -- but with file-format awareness, and giving you the ability to refer to fields by name.
+The verb is optional: if you omit it, Miller behaves as if you had written [`cat`](reference-verbs.md#cat), which is handy for pure format conversions such as `mlr --c2j < input.csv`.
+
The verbs `put` and `filter` are special in that they have a rich expression language (domain-specific language, or "DSL"). More information about them can be found on the [Intro to Miller's Programming Language page](miller-programming-language.md); see also the [DSL Reference](reference-dsl.md) for more details.
Here's a comparison of verbs and `put`/`filter` DSL expressions:
diff --git a/docs/src/reference-main-overview.md.in b/docs/src/reference-main-overview.md.in
index 42c3b8f0c..cd36e3583 100644
--- a/docs/src/reference-main-overview.md.in
+++ b/docs/src/reference-main-overview.md.in
@@ -35,6 +35,8 @@ See also the [Glossary](glossary.md) for more about terms such as
When you type `mlr {something} myfile.dat`, the `{something}` part is called a **verb**. It specifies how you want to transform your data. Most of the verbs are counterparts of built-in system tools like `cut` and `sort` -- but with file-format awareness, and giving you the ability to refer to fields by name.
+The verb is optional: if you omit it, Miller behaves as if you had written [`cat`](reference-verbs.md#cat), which is handy for pure format conversions such as `mlr --c2j < input.csv`.
+
The verbs `put` and `filter` are special in that they have a rich expression language (domain-specific language, or "DSL"). More information about them can be found on the [Intro to Miller's Programming Language page](miller-programming-language.md); see also the [DSL Reference](reference-dsl.md) for more details.
Here's a comparison of verbs and `put`/`filter` DSL expressions:
diff --git a/docs/src/reference-verbs.md b/docs/src/reference-verbs.md
index 724f5bcd9..342c9d292 100644
--- a/docs/src/reference-verbs.md
+++ b/docs/src/reference-verbs.md
@@ -274,7 +274,27 @@ Options:
## cat
-Most useful for format conversions (see [File Formats](file-formats.md)) and concatenating multiple same-schema CSV files to have the same header:
+Most useful for format conversions (see [File Formats](file-formats.md)) and concatenating multiple same-schema CSV files to have the same header.
+
+`cat` is also the default verb: if you omit the verb entirely, Miller behaves as if you had written `cat`. This makes pure format conversions more concise:
+
+
+mlr --c2j < data/a.csv
+
+
+[
+{
+ "a": 1,
+ "b": 2,
+ "c": 3
+},
+{
+ "a": 4,
+ "b": 5,
+ "c": 6
+}
+]
+
mlr cat -h
@@ -1828,7 +1848,7 @@ Same, but showing only unpaired records:
data/join-right-example.csv
-status idcode
+status id
missing 600
id name
diff --git a/docs/src/reference-verbs.md.in b/docs/src/reference-verbs.md.in
index 5f6f31097..adedd4829 100644
--- a/docs/src/reference-verbs.md.in
+++ b/docs/src/reference-verbs.md.in
@@ -155,7 +155,13 @@ GENMD-EOF
## cat
-Most useful for format conversions (see [File Formats](file-formats.md)) and concatenating multiple same-schema CSV files to have the same header:
+Most useful for format conversions (see [File Formats](file-formats.md)) and concatenating multiple same-schema CSV files to have the same header.
+
+`cat` is also the default verb: if you omit the verb entirely, Miller behaves as if you had written `cat`. This makes pure format conversions more concise:
+
+GENMD-RUN-COMMAND
+mlr --c2j < data/a.csv
+GENMD-EOF
GENMD-RUN-COMMAND
mlr cat -h
diff --git a/man/manpage.txt b/man/manpage.txt
index c505c8ee4..e55be814b 100644
--- a/man/manpage.txt
+++ b/man/manpage.txt
@@ -5,9 +5,13 @@
as CSV and tabular JSON.
1mSYNOPSIS0m
- Usage: mlr [flags] {verb} [verb-dependent options ...] {zero or more
+ Usage: mlr [flags] [verb] [verb-dependent options ...] {zero or more
file names}
+ If no verb is given, "cat" is used, which is handy for format
+ conversions, e.g.
+ mlr --c2j < example.csv
+
If zero file names are provided, standard input is read, e.g.
mlr --csv sort -f shape example.csv
@@ -3825,4 +3829,4 @@
MIME Type for Comma-Separated Values (CSV) Files, the Miller docsite
https://miller.readthedocs.io
- 2026-05-16 4mMILLER24m(1)
+ 2026-05-17 4mMILLER24m(1)
diff --git a/man/mlr.1 b/man/mlr.1
index 7108bfde8..f1eca6002 100644
--- a/man/mlr.1
+++ b/man/mlr.1
@@ -2,12 +2,12 @@
.\" Title: mlr
.\" Author: [see the "AUTHOR" section]
.\" Generator: ./mkman.rb
-.\" Date: 2026-05-16
+.\" Date: 2026-05-17
.\" Manual: \ \&
.\" Source: \ \&
.\" Language: English
.\"
-.TH "MILLER" "1" "2026-05-16" "\ \&" "\ \&"
+.TH "MILLER" "1" "2026-05-17" "\ \&" "\ \&"
.\" -----------------------------------------------------------------
.\" * Portability definitions
.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -29,7 +29,10 @@
Miller \-\- like awk, sed, cut, join, and sort for name-indexed data such as CSV and tabular JSON.
.SH "SYNOPSIS"
.sp
-Usage: mlr [flags] {verb} [verb-dependent options ...] {zero or more file names}
+Usage: mlr [flags] [verb] [verb-dependent options ...] {zero or more file names}
+
+If no verb is given, "cat" is used, which is handy for format conversions, e.g.
+ mlr --c2j < example.csv
If zero file names are provided, standard input is read, e.g.
mlr --csv sort -f shape example.csv
diff --git a/pkg/climain/mlrcli_parse.go b/pkg/climain/mlrcli_parse.go
index 5963fc985..78837b557 100644
--- a/pkg/climain/mlrcli_parse.go
+++ b/pkg/climain/mlrcli_parse.go
@@ -245,9 +245,14 @@ func parseCommandLinePassOne(
}
if len(verbSequences) == 0 {
- fmt.Fprintf(os.Stderr, "%s: no verb supplied.\n", "mlr")
- help.MainUsage(os.Stderr)
- os.Exit(1)
+ // Bare 'mlr' with no flags, no verb, and no files: keep the
+ // friendly usage banner. Anything else (e.g. 'mlr --c2j' on a
+ // piped stdin) defaults to 'cat'.
+ if argc == 1 {
+ help.MainUsage(os.Stderr)
+ os.Exit(1)
+ }
+ verbSequences = append(verbSequences, []string{"cat"})
}
}
diff --git a/pkg/terminals/help/entry.go b/pkg/terminals/help/entry.go
index 31d752e5f..6a9ed0563 100644
--- a/pkg/terminals/help/entry.go
+++ b/pkg/terminals/help/entry.go
@@ -244,7 +244,10 @@ func HelpMain(args []string) int {
func MainUsage(o *os.File) {
fmt.Fprintf(o,
- `Usage: mlr [flags] {verb} [verb-dependent options ...] {zero or more file names}
+ `Usage: mlr [flags] [verb] [verb-dependent options ...] {zero or more file names}
+
+If no verb is given, "cat" is used, which is handy for format conversions, e.g.
+ mlr --c2j < example.csv
If zero file names are provided, standard input is read, e.g.
mlr --csv sort -f shape example.csv
diff --git a/test/cases/cli-default-verb-cat/0001/cmd b/test/cases/cli-default-verb-cat/0001/cmd
new file mode 100644
index 000000000..728315268
--- /dev/null
+++ b/test/cases/cli-default-verb-cat/0001/cmd
@@ -0,0 +1 @@
+mlr --j2y < ./${CASEDIR}/input
diff --git a/test/cases/cli-default-verb-cat/0001/experr b/test/cases/cli-default-verb-cat/0001/experr
new file mode 100644
index 000000000..e69de29bb
diff --git a/test/cases/cli-default-verb-cat/0001/expout b/test/cases/cli-default-verb-cat/0001/expout
new file mode 100644
index 000000000..7249bd885
--- /dev/null
+++ b/test/cases/cli-default-verb-cat/0001/expout
@@ -0,0 +1,3 @@
+- b: 22
+ c: 33
+ a: 11
diff --git a/test/cases/cli-default-verb-cat/0001/input b/test/cases/cli-default-verb-cat/0001/input
new file mode 100644
index 000000000..5fa6201b6
--- /dev/null
+++ b/test/cases/cli-default-verb-cat/0001/input
@@ -0,0 +1 @@
+{"b":22,"c":33,"a":11}
diff --git a/test/cases/cli-default-verb-cat/0002/cmd b/test/cases/cli-default-verb-cat/0002/cmd
new file mode 100644
index 000000000..8eef97542
--- /dev/null
+++ b/test/cases/cli-default-verb-cat/0002/cmd
@@ -0,0 +1 @@
+mlr --c2p < ./${CASEDIR}/input
diff --git a/test/cases/cli-default-verb-cat/0002/experr b/test/cases/cli-default-verb-cat/0002/experr
new file mode 100644
index 000000000..e69de29bb
diff --git a/test/cases/cli-default-verb-cat/0002/expout b/test/cases/cli-default-verb-cat/0002/expout
new file mode 100644
index 000000000..d0c04ad13
--- /dev/null
+++ b/test/cases/cli-default-verb-cat/0002/expout
@@ -0,0 +1,3 @@
+a b c
+1 2 3
+4 5 6
diff --git a/test/cases/cli-default-verb-cat/0002/input b/test/cases/cli-default-verb-cat/0002/input
new file mode 100644
index 000000000..88700c714
--- /dev/null
+++ b/test/cases/cli-default-verb-cat/0002/input
@@ -0,0 +1,3 @@
+a,b,c
+1,2,3
+4,5,6
diff --git a/test/cases/cli-default-verb-cat/0003/cmd b/test/cases/cli-default-verb-cat/0003/cmd
new file mode 100644
index 000000000..beaf65901
--- /dev/null
+++ b/test/cases/cli-default-verb-cat/0003/cmd
@@ -0,0 +1 @@
+mlr --icsv --ojson --from test/input/example.csv
diff --git a/test/cases/cli-default-verb-cat/0003/experr b/test/cases/cli-default-verb-cat/0003/experr
new file mode 100644
index 000000000..e69de29bb
diff --git a/test/cases/cli-default-verb-cat/0003/expout b/test/cases/cli-default-verb-cat/0003/expout
new file mode 100644
index 000000000..4277e2c14
--- /dev/null
+++ b/test/cases/cli-default-verb-cat/0003/expout
@@ -0,0 +1,92 @@
+[
+{
+ "color": "yellow",
+ "shape": "triangle",
+ "flag": "true",
+ "k": 1,
+ "index": 11,
+ "quantity": 43.64980000,
+ "rate": 9.88700000
+},
+{
+ "color": "red",
+ "shape": "square",
+ "flag": "true",
+ "k": 2,
+ "index": 15,
+ "quantity": 79.27780000,
+ "rate": 0.01300000
+},
+{
+ "color": "red",
+ "shape": "circle",
+ "flag": "true",
+ "k": 3,
+ "index": 16,
+ "quantity": 13.81030000,
+ "rate": 2.90100000
+},
+{
+ "color": "red",
+ "shape": "square",
+ "flag": "false",
+ "k": 4,
+ "index": 48,
+ "quantity": 77.55420000,
+ "rate": 7.46700000
+},
+{
+ "color": "purple",
+ "shape": "triangle",
+ "flag": "false",
+ "k": 5,
+ "index": 51,
+ "quantity": 81.22900000,
+ "rate": 8.59100000
+},
+{
+ "color": "red",
+ "shape": "square",
+ "flag": "false",
+ "k": 6,
+ "index": 64,
+ "quantity": 77.19910000,
+ "rate": 9.53100000
+},
+{
+ "color": "purple",
+ "shape": "triangle",
+ "flag": "false",
+ "k": 7,
+ "index": 65,
+ "quantity": 80.14050000,
+ "rate": 5.82400000
+},
+{
+ "color": "yellow",
+ "shape": "circle",
+ "flag": "true",
+ "k": 8,
+ "index": 73,
+ "quantity": 63.97850000,
+ "rate": 4.23700000
+},
+{
+ "color": "yellow",
+ "shape": "circle",
+ "flag": "true",
+ "k": 9,
+ "index": 87,
+ "quantity": 63.50580000,
+ "rate": 8.33500000
+},
+{
+ "color": "purple",
+ "shape": "square",
+ "flag": "false",
+ "k": 10,
+ "index": 91,
+ "quantity": 72.37350000,
+ "rate": 8.24300000
+}
+]
diff --git a/test/cases/cli-default-verb-cat/0004/cmd b/test/cases/cli-default-verb-cat/0004/cmd
new file mode 100644
index 000000000..4fe92612e
--- /dev/null
+++ b/test/cases/cli-default-verb-cat/0004/cmd
@@ -0,0 +1 @@
+${MLR}
diff --git a/test/cases/cli-default-verb-cat/0004/experr b/test/cases/cli-default-verb-cat/0004/experr
new file mode 100644
index 000000000..a0e8d6ffc
--- /dev/null
+++ b/test/cases/cli-default-verb-cat/0004/experr
@@ -0,0 +1,13 @@
+Usage: mlr [flags] [verb] [verb-dependent options ...] {zero or more file names}
+
+If no verb is given, "cat" is used, which is handy for format conversions, e.g.
+ mlr --c2j < example.csv
+
+If zero file names are provided, standard input is read, e.g.
+ mlr --csv sort -f shape example.csv
+
+Output of one verb may be chained as input to another using "then", e.g.
+ mlr --csv stats1 -a min,mean,max -f quantity then sort -f color example.csv
+
+Please see 'mlr help topics' for more information.
+Please also see https://miller.readthedocs.io
diff --git a/test/cases/cli-default-verb-cat/0004/expout b/test/cases/cli-default-verb-cat/0004/expout
new file mode 100644
index 000000000..e69de29bb
diff --git a/test/cases/cli-default-verb-cat/0004/should-fail b/test/cases/cli-default-verb-cat/0004/should-fail
new file mode 100644
index 000000000..e69de29bb