I’ve run across comments regarding useless use of cat twice today. However, after reading the linked Wikipedia entry, it feels more like a way to give someone an ego trip than a truly more useful alternative.
The Wikipedia article even concedes that cat might be better:
> A cat written with UUOC might still be preferred for readability reasons, as reading a piped stream left-to-right might be easier to conceptualize.[10] Also, one wrong use of the redirection symbol ">" instead of "<" (often adjacent on keyboards) may permanently delete the content of a file, in other words clobbering, and one way to avoid this is to use cat with pipes.
I‘ll happily continue to “abuse cat” going forward and sleep perfectly well.
Hopefully this[0] should be the last word on "useless" uses of cat
> When I offer a pipeline as a solution I expect it to be reusable. It is quite likely that a pipeline would be added at the end of or spliced into another pipeline. In that case having a file argument to grep screws up reusability, and quite possibly do so silently without an error message if the file argument exists. I. e. `grep foo xyz | grep bar xyz | wc` will give you how many lines in xyz contain bar while you are expecting the number of lines that contain both foo and bar. Having to change arguments to a command in a pipeline before using it is prone to errors. Add to it the possibility of silent failures and it becomes a particularly insidious practice.
See Jonathan Leffler's comment on SO (also demonstrated by the the top-level parent comment here):
> As noted in the answer by kojiro, it is perfectly possible and legal to start the pipeline with `< file command1 ...`. Although the conventional position for the I/O redirection operators is after the command name and its arguments, that is only the convention and not a mandatory placement. The `<` does have to precede the file name. So, there's a close to perfect symmetry between `>output` and `<input` redirections: `<input command1 -opt 1 | command2 -o | command3 >output`.
Sure, and as another answerer of that SO question points out[0]:
> We are used to read from left to right, so a command like
> `cat infile | process1 | process2 > outfile`
> is trivial to understand.
> `process1 < infile | process2 > outfile`
> has to jump over process1, and then read left to right. This can be healed by:
> `< infile process1 | process2 > outfile`
> looks somehow, as if there were an arrow pointing to the left, where nothing is.
Sure, you can have the inputfile precede the process, but then you have to precede _that_ with a glyph which appears to suggest "send this data to the preceding command". You know and I know that that's not what `<infile` really means, but I claim (and others are free to subjectively disagree) that, in the context of an exploratory gradually-incrementing bash query, the extra brain cycles to remember what `<infile` really means are not worth the extra compute cycles of the extra process of a "useless" cat.
To someone who's fully internalized the workings of the shell, then sure, using `<infile` is _technically_ more efficient, at the expense of being less readable to less-experienced engineers. The tradeoff between readability and performance is always a case-by-case decision.
There is room for other interpretations, but I'd say if it's super common for people to not know something, which appears to describe this, it doesn't meet the definition of basic.
I'd say "basic" shell knowledge is that commands or programs produce output which is where many stop and why it's common to use cat this way.
In general I tend to err less on the side of "you're holding it wrong" gatekeeping in tech and when there's a common issue with something, blame the tech rather than the users. Maybe the way shell handles input, output, and redirection isn't intuitive and poorly designed. For those that already know there's an ego thing going on condescending to users who haven't learned as much that prevent honest or productive conversations on these topics.
> In general I tend to err less on the side of "you're holding it wrong" gatekeeping in tech
That's not gatekeeping. I'm pretty sure anyone that points out `<` would like anyone that doesn't know it to become familiar with it. That's precisely why they mention it. To gatekeep would be for someone to say that people that aren't familiar with it shouldn't have access to the shell. No one is saying that.
> There is room for other interpretations, but I'd say if it's super common for people to not know something, which appears to describe this, it doesn't meet the definition of basic. I'd say "basic" shell knowledge is that commands or programs produce output which is where many stop and why it's common to use cat this way.
I feel that's the same bar as saying that knowing how to use a keyboard and mouse is not basic because most people just learn to use their phone's touch interface, given how there's now a lot of people that have a smartphone but not a computer. I don't mean in our circles, but in general.
What's probably going on is that the boundary between basic and intermediate probably moves depending on increased adoption with different proportions of motivations. That is, most learners of the shell before were probably motivated to use it as their main interface, later one of their main interfaces, and now maybe there's a lot of people that need to run a command or 2 but don't really want to use it as an interface at all, so they never bother to learn beyond the most absolute minimum they need to.
> Maybe the way shell handles input, output, and redirection isn't intuitive and poorly designed.
I don't think being intuitive is always the most important criteria to something being well designed. Many things imply trade-offs, and for example if the average potential user values versatility over intuitiveness, and there's a tradeoff to be made between the 2, it's ok to not go for the intuitive option.
That said, the redirection operators seem as intuitive as they can be. Arrow from file to command for input, arrow from command to file for output. What's a better alternative? To just remove file redirection features and leave piping?
Processes will have inheritable file descriptors. Right now, the easiest and quickest way to make ad-hoc arbitrary arrangements of file descriptors is with the shell's file redirection features. Doing it on anything else (Python, C, whatever) requires more code. That seems like successful design to me.
> Honestly I don't think that in 15+ years I ever saw that in the wild in any shell script
I've done it in shell scripts, very rarely interactively. In scripts, it sometimes just looks better defining that part first.
Wait until you see the redirect in the middle of program arguments. That's where it gets confusing. At least the redirect at the very beginning or very end of the line is easy. :)
"from day one", there's a lot of more important stuff to learn on day 1 than one "weird trick" that literally has no tangible benefits other than nerd sniping
I have more important things to worry about than making the line less readable and less maintainable
I have been aware of this feature for 20 year. I have also 20 years of muscle memory that makes me type the redundant cat. If you are used to it, it is hard to avoid and the benefit as minuscule. Also sometimes it makes it easer to extend the pipeline
> Briefly, here's the collected wisdom on using cat:
> The purpose of cat is to concatenate (or "catenate") files. If it's only one file, concatenating it with nothing at all is a waste of time, and costs you a process. The fact that the same thread ("but but but, I think it's cleaner / nicer / not that much of a waste / my privelege to waste processes!") springs up virtually every time the Award is posted is also Ancient Usenet Tradition.
Catenating a file with the output stream is quite useful in many circumstances. Paged data isn't always wanted, and it's not generally known if filters are needed before the file is seen. Cat is the standard way to print to stdout.
The actual command is "cat mario.nes - | nc ...”
The trailing dash allows you to actually control the game after the rom has been loaded.