1. 19
  1.  

    1. 49

      Ah yes, one of the super toxic throw away comments anyone can make which alienates one participant and makes the other feel super smug.

      These things are mostly going away, phone keyboards killed the “grammar nazi”, no one can spell anymore and no one knows who is at fault. I’m looking forward to a world where our default isn’t trying to win the conversation, but to move it forward more productively.

      1. 5

        The venerable Randal L. Schwartz hands out Useless Use of Cat Awards from time to time

        Ah yes, “the good old days”

        1. 11

          The 1990s were so good that some people’s biggest problem was other people wasting a process in their shell scripts. 🙃

        2. 5

          I’m looking forward to a world where our default isn’t trying to win the conversation, but to move it forward more productively.

          Probably a bit optimistic

          On UUOC: I suspect it was originally in the spirit of fun. It becoming a cultural gatekeeping tool (as many, many in-group signifiers become) is a separate phenomenon and I think it’s probably best to view it as such

          1. 3

            it was originally in the spirit of fun.

            IMO the issue is that pointing at other people’s code and saying “lol that’s dumb” is really only something you can do with friends, with strangers over the internet it’s a very different thing

            1. 3

              Often, people in these forums are friends to some extent and I’d assume that part of this that became toxic is that since you’re not ALL friends, it’s hard to tell who knows who and what’s a joke and what’s a dig.

        3. 34

          My favorite useful use of cat:

          cat foo | grep bar

          “but Nelson”, you’ll say, “you can just do grep bar foo or grep bar < foo”. Yes, yes I could. but the next thing I’m going to do is

          zcat foo.gz | grep bar

          or maybe

          cat foo baz | grep bar

          or maybe

          awk 'blah blah' foo | grep bar

          and all of those things are way less edit distance in my readline editor than if I’d done the “optimal” thing in the first place. Note the end of the command doesn’t change. That gets real handy when it’s a long pipe and not just a single grep.

          Always optimize the programmer’s time for one-off hacking.

          (And all this before we even get to the topic of how many programs function differently if it thinks it’s talking to a tty or a pty. I do ls | cat all the damn time just to eliminate the colors when I need to.)

          1. 4

            I strongly agree.

            A huge part of the productivity of the shell is interactively and iteratively building up a series of transformations to do something.

            1. 2

              Depends.

              Some older programs such as col(1) would require ‘<’ redirection due to ioctl() reasons.

            2. 3

              and all of those things are way less edit distance in my readline editor than if I’d done the “optimal” thing in the first place.

              I feel like UUOC should not apply for interactive use; the time and resources it takes to execute cat is nonexistent compared to the amount of time it takes to refactor your pipeline to work around it. Shell scripts are a different story, as I have seen UUOCs legitimately result in slowdowns, although most are fairly benign as well.

              1. 2

                For what it’s worth, you can do < foo grep bar.

                1. 17

                  Yes, but just < foo doesn’t work, so it’s still worse for iteratively building up a pipeline. I could remember all these special cases and workarounds, or I could just use “useless” cat and be at peace.

                  1. 5

                    Yes, but just < foo doesn’t work

                    It does in zsh (as long as you don’t unset NULLCMD and READNULLCMD).
                    But I still use cat, easier to type and composes better.

              2. 22

                Many accusations that a cat is useless are technically wrong as well as obnoxious. They typically neglect the fact that unix is an interactive programming environment and shell programs are often composed incrementally. This is easiest to do left-to-right. And in scripts, redundant commands can make pipelines easier to read, so they aren’t useless.

                Recently I have been comparing a collection of source trees. I start off by working out which subset of files I am interested in, eventually resulting in a command like

                ls ~/path/to/repo/subdir/*glob*
                

                Then I operate on those files with commands like

                ls ~/path/to/repo/subdir/*glob* | xargs wc -l
                

                Which might seem like a useless use of ls and a useless use of xargs, but I can uparrow to find a previous instance of the analysis, ctrl-k to chop it off the end of the command line, and ctrl-y to append it to the latest ls command. This still works when the analysis is a multi-stage pipeline.

                1. 1

                  I absolutely agree with your point, but not with your example. Not because it’s useless - it isn’t - but because parsing ls can be dangerous.

                  I often build my pipeline with a short for-loop in zsh instead:

                  for f in ~/path/to/repo/subdir/*glob*; wc -l $f
                  

                  Exchanging wc -l for echo (or even cat) here allows for much of the same flexibility as in your example :)

                  1. 2

                    You’re neglecting the fact that I was using unix as an interactive programming environment and my shell programs were composed incrementally. I wrote that I looked at the output of ls first, so of course I knew the rest of the pipeline would work safely. I wrote the ls commands before I knew I would need more automation, so it was much more convenient to append an xargs (which I could copy and paste) than to edit half a dozen ls commands.

                2. 14

                  One more reason not yet mentioned to prefer cat: it provides some degree of assurance that the named file won’t accidentally be written to instead of read from

                  1. 7

                    try this Alta Vista search instead

                    Wow, this was written before Google was the thing

                    1. 7

                      Note that although in most circumstances cat file | stuff is unnecessary and should just be stuff < file, the difference is significant in certain contexts. E.g. I was working on a program that uses splice(2) on standard input, which won’t work if standard input is an actual file (or a character device), so cat file | stuff and cat | stuff would work while stuff < file and stuff would not.

                      1. 6

                        Are there any shells where cat is a builtin? I’d have thought it would be trivial for a shell to turn cat with a single argument into a redirect.

                        1. 4

                          The real gem is at the end:

                          Just another Useless Use of Usenet

                          1. 3

                            One nice thing I found when trying to avoid “useless” cat invocations was that files can be piped like < myfile grep "foo" | bar | baz, which I find nicer than the more-common grep "foo" < myfile | bar | baz since it reads left-to-right. Previously I would achieve the same using cat myfile | grep "foo" | bar | baz.

                            Not a big deal, but nice to learn more about the shell I use everyday :-)

                            1. 3

                              UUoC has been discussed many times, e.g. https://lobste.rs/s/jfydw6/turn_shell_commands_into_apis#c_epmju3

                              It should be seen as a food for thought that encourages seeing things from different angles, rather that a stick to beat others with.

                              1. 2

                                This gives an example of a useful use of cat:

                                { foo; bar; cat mumble; baz } | whatever
                                

                                It’s always bugged me that bash can replace $(cat file) with $(< file) to read a file without any subprocesses, but if you just type < file at the prompt it doesn’t do anything (besides error if the file doesn’t exist).

                                1. 6

                                  It’s a shame UNIX wasn’t designed as a capability system. In a capability system, the shell would be responsible for opening files and passing them as file descriptors to each invoked command. UNIX has an awkward mix where the shell is responsible for passing in three file descriptors but other files are expected to be opened by the command itself.

                                  In my ideal world, programs would start in capsicum mode and you’d get a parallel array alongside argv that told you which file descriptor numbers any file or directory arguments had been passed as. If you did cat foo then argv[1] would be the string ”foo” but fdv[1] would be 3 and the shell would pass an open file handle to foo in as file descriptors 3. You’d also then be able to tweak the command in the shell, to pass a read-only file descriptor instead of a read-write one (since cat doesn’t need write access to the input file).

                                  Once you’re in that model, it’s easy to have a consistent concept that the shell is always the thing that does file name to file descriptor mappings and you can make that much more consistent in the shell syntax.

                                  If you were to retrofit this to existing systems, you’d probably manage it via an environment variable rather than an additional argument to main.