6 ms·
I have to strongly disagree with "useless use of cat". Using cat first have 3 main advantages making it vastly superior: 1. It allows you to drop context quick
by dvh 3y ago
I have to strongly disagree with "useless use of cat". Using cat first have 3 main advantages making it vastly superior:
1. It allows you to drop context quickly and focus on algorithm. You write "cat filename" and you can free your mind and focus on the rest of the pipes. Without cat, you have to keep filename in your mind while you write the first command.
2. It puts filename closer to the beginning so when you need to repeat for few more files, you just press home and one Ctrl+right, whereas without cat, you would have to move several times right depending on how many switches first command needed which is always random. Plus most of the back and forth switch editing will be in the first command and filename would just get in the way.
3. It works the same for every app. Some apps need file as last parameter, some needs -i, or whatever switch, some use some other random scheme. Cat is always the same.
- emeraldd 3y agoI honestly have to agree ... I tend to use cat because I don't always know what the next thing in my pipeline is going to be and frequently change out later steps in the pipeline. Putting the real first operation in place of cat means it's harder to reuse a particular idiom or "stage" parts of a pipeline that might be slow in a temp file while you're figuring out how to string things together.
- vsviridov 3y agoI build pipes left to right, and I read pipes left to right... 1 -> 2 -> 3 is easier that (2 <- 1) -> 3
- samsquire 3y agoYou can put shell file redirections such as "< file" at the beginning of the line. In bash, type: < /etc/resolv.conf grep nameserver (That < is not a prompt, that's the less than symbol)
- tolciho 3y agoSometimes you can prefix with "< file". Sometimes, not so much. < /etc/passwd while IFS= read line || [ -n "$line" ]; do printf '%s\n' "$line"; done Meanwhile, in ZSH... Meanwhile, in languages that do not need IFS= and || [ -n "$line" ] checks...
- kzrdude 3y agoNice, I learned something and thank you
- ilyt 3y agoaliasing c to cat still requires less keystrokes
- antonvs 3y agoBut in a multi-step pipe, that’s still asymmetric and to me, less natural as a result. cat f | grep nameserver | otherproc… …is more consistently compositional.
- throwaway173738 3y agoThis is also the classic argument against reverse polish notation. Operator-first makes it harder to say the name of an operator in a sentence.
- ajuc 3y agoReverse polish notation is operator last.
- eru 3y agoOperator first makes the sentence easier: '+ 2 3' becomes 'add 2 and 3' In any case, it's a silly objection.
- pxc 3y agoIt's an especially silly objection in the case of the command line, where prefix notation is already the norm anyway. + 2 3 is naturally how you'd write addition if addition were a standalone Unix command!
- jrockway 3y agoInfix operators are very weird, though. They come from math, where every elementary school student has to memorize "please excuse my dear aunt sally" to be able to answer a simple question like "what is 2³ + 4 ÷ 2". C copied this concept, and nobody really ever bothered to memorize C's operator precedence, so they just end up writing Lisp but with the operators in the middle. pow(2, 3) + (4/2). Note that some operators appear prefix instead of infix for no apparent reason. (You can't just remember what you learned in math class when writing a computer program, because now we have bitwise and, or, xor, left shift, right shift, equality, pointer dereferencing, assignment, logical and, or, modulo, pre-increment, post-increment, bitwise not, logical not, etc. So you have to learn it all again. And it's different for every language.) Put everything up front, and suddenly you don't have to think about this anymore. (+ (expt 2 3) (/ 4 2)). The computer just does what you say and there are no rules to memorize. Personally, I always use RPN calculators (dc is my favorite), because I don't trust the calculator to remember operator precedence. They usually do it right, but it's difficult to reason about. (The example would be "2 3 ^ 4 2 / + p" in dc.)
- sverona 3y agoA good friend of mine called "cat file.txt" UUOC on the grounds I should have run "less file.txt". If you're writing a script, sure. If it's the first step in a pipeline that you're typing on the fly, does it really matter?
- levihaku 3y agocat file.txt is always worthless. Best case scenario, you will end up with text that fits into one scree, but more often than not you will have to retype the command with $EDITOR filename or less filename anyway and now you just wasted (precious) time doing what could've been done few seconds ago. Sure, few seconds isn't a lot, to someone who opens terminal once a year.
- sverona 3y agoSure, if I know it's bigger than my screen I'll open another terminal and use less. But I can generally tell if that's the case from the filesize.
- omnibrain 3y agoDepends on how your terminal(-emulator) behaves in conjunction with the scroll lock key.
- pxc 3y agoIf you're using a terminal multiplexer to handle scrollback, you can navigate the output using your usual pager whether you explicitly invoked it in the pipeline or not. And that leaves it searchable in your scrollback history even after you've gone on to run several more commands, unlike if you pipe it directly to a pager. Additionally, if you're using a nicer colorizing pager, like bat, it'll automatically send the output to your pager for you when it detects that the output wouldn't fit on screen. For both of those reasons, I almost never use `less` directly on a file.
- darkwater 3y agoFirst case is good, the second one feels like cheating, if you are using a cat substitute like bat, well, you are not using cat already.
- xorvoid 3y agoI came here to say the same haha. It’s like an “article” or “preposition” in English. Arguably not required, but in practice invaluable. One could argue that shell could have been designed better to not need it but, meh, that ship sailed. Uses of “cat” are ubiquitous and excellent. Not sure why people remotely care when there are bigger problems to worry about.
- lucideer 3y agoThere was a recent thread on HN about generating HTML using string templates, arguing that if users keep on doing something for years despite constant recommendations against it, the recommendations must be wrong. I didn't agree with it - it's an ok rule of thumb in moderation but I don't think HTML string templates are a good example. But, `cat` is absolutely the perfect example. I use shellcheck which automatically corrects all my "useless" uses of cat, and I can tell you there's no more common error in other people's code that it complains about. And the benefits of "fixing" this error are always so marginal, the resultant code so much less readable.
- dllthomas 3y agoThese advantages are generally shared by simply opening with "<filename" instead of "cat filename |".
- alex_smart 3y agoI have honestly not seen a more egregious case of "premature optimization". Who the fuck cares about 1% extra performance on something they are doing on the interactive shell? (And the answer wouldn't even change if the performance difference was 100%.) What an utterly useless thing to get pedantic about.
- arendtio 3y agoI also like 'cat file | ...' pattern better, but I can also understand people who say that using the '<file ...' pattern is cleaner. So as long as people don't cry 'useless use of cat' we get along ;-)
- ilyt 3y agoIt's just OCD people not having anything to bitch about in life. But to add to the point: 4. You are just ctrl-a away from changing source the common use for me for example cat f.log |grep sth # okay it shows in history; C-a tail -f f.log | grep sth # let's try to repeat it live; C-a zcat f.log.1.gz | grep sth # no dice, let's try to dig a bit in history
- paulddraper 3y ago< file command Is perfectly valid. To me, it just makes sense to put input on the left of a pipeline. IDK why others don't, but :shrug:
- gorgoiler 3y agoNot that it really matters, but on your second point: $ <example.json jq [ 1, 2, 3 ] …but if you are using a POSIXish shell, which I do not (fish).
- somat 3y agoI agree, I use cat all the time, it is a normalization of access patterns. it lets you isolate the file input and output into it's own section of the pipeline. There is nothing wrong with using the shell redirection operators but I like seeing the input and output in it's own explicit pipeline section. get file data and put it on the pipe: cat get pipe data and put it in a file: tee (with huge caveat you have to do something with stdout so you still need to mess around with the redirection operators. tee does not really gain you any normalization. Sigh. I would make a tee that is just "tee > /dev/null" but I am used to it at this point. Stockholm syndrome?)
- AtlasBarfed 3y agopipes have an inherent data-first natural order processing that is counter to most programming languages <take this file> | <do this to the file> | <then do this> And UNIX philosophy says that is a good thing. I takes a universal UNIX technique (the pipe) and the programs just have to concentrate on processing input and output. Sure you CAN use the args. Look up the fucking specific flag and syntax after the bajillion flags in the man pages (which all seem to lack good examples that would communicate this much more quickly. But the cat | jp seems FAR more UNIXy. I agree, it is stupid to criticize cat there. This is pointless fad thinking by the author. Ignore it. There MAY be certain performance advantages possibly in certain high volume conditions like large files or something similar, if the program has "better" file processing than cat + a pipe. Maybe. Anyway, I really like the data flow of a pipe command like: cat <somefile> | sort | head -n 10 Meanwhile, this is how a programming language would look (one liner version): head( sort( cat(<somefile) ), 10) The logical flow of that, where you get data, sort it, then head it, is natural in the piped instance, but the practically every language ever version of it you need to parse the expression first, extract the inner steps, subparse / resolve the args to the head, then get the value. The expression is "inside out" in a normal progarmming language. You have to turn it inside out: PUSH head op on the stack, PUSH sort onto the stack, resolve CAT, POP sort op, POP stack op. The CLI + pipes has no stack, just a handoff I have started doing "data first" programming a lot with say Groovy, where you can do: String passed_in_filename = "/path/to/file" passed_in_filename. with { File.lines(it)}. with { it.sort()}. with { it.head(10)} with a lot of the I/O or transform data code I write. (The with construct in groovy takes the output of the invoked code and then passes it to the provided closure, so I can chain the closures in the natural way that piped output works on the CLI)
- plq 3y ago> You write "cat filename" and you can free your mind and focus on the rest of the pipes. Without cat, you have to keep filename in your mind while you write the first command. In bash (don't know about other shells) the < operator sets the stdin of the process to the given file. < filename.json jq Here, data is read directly from the given file. As for the | operator, the stdout of the left-hand process and the stdin of the right-hand process become a pipe: cat filename.json | jq Here, data is read from file, copied to a pipe buffer, the other process is notified (in most cases, by being woken up) that there is incoming data and then it finally reads the data. Not that any of this matters in today's world of pocket supercomputers but I just don't see how any of your points back up the useless use of cat. It's still useless :)
- yesco 3y agoThe cat and pipe are semantically easier to understand though, at least that has been my experience when onboarding new hires. While Bash has all sorts of nice bells and whistles for various use-cases, I really think they are only worth relying on when you are doing something highly specific. In general mastering wildcards and pipes is sufficient for the vast majority of situations, I think for everything else it's better to use commands that people can easily search or find the man page for. In the world of pocket supercomputers as you called it, interface is king. So I'd argue that if anything, `<` is the useless one here when we can could just have just used the more semantically obvious cat and pipe instead.