But this is not really practical for many use cases which are not filters first and foremost. So we end up with still reading from STDIN or the list of files presented as arguments. We write to the file given by -o (or --output) which can be "-" to signify STDOUT.
I find this pattern very flexible because it allows multiple input files or STDIN and a single output file which can be STOUT, so you still get your filtering behaviour if you want.
(For completeness sake, there is a third pattern somewhat prevalent. In call these copy type programs. They treat the last argument specially, usually as some form of target, like `cp a b c target`.)