News for hackers. Stuff that matters.
Re:A Terminal Case of Linux by dvh on Monday May 29, 2023 @01:49PM (#36116208)
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.

Re:A Terminal Case of Linux by lucideer on Monday May 29, 2023 @02:34PM (#36116590)
There 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.

Re:A Terminal Case of Linux by xorvoid on Monday May 29, 2023 @02:32PM (#36116572)
I 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.

Re:A Terminal Case of Linux by emeraldd on Monday May 29, 2023 @01:53PM (#36116249)
I 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.
Re:A Terminal Case of Linux by sverona on Monday May 29, 2023 @02:10PM (#36116399)
A 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?
Re:A Terminal Case of Linux by levihaku on Monday May 29, 2023 @03:13PM (#36116976)
cat 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.

Re:A Terminal Case of Linux by omnibrain on Monday May 29, 2023 @03:19PM (#36117034)
Depends on how your terminal(-emulator) behaves in conjunction with the scroll lock key.
Re:A Terminal Case of Linux by pxc on Monday May 29, 2023 @04:44PM (#36117915)
If 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.

Re:A Terminal Case of Linux by darkwater on Monday May 29, 2023 @05:36PM (#36118386)
First 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.
Re:A Terminal Case of Linux by pxc on Monday May 29, 2023 @05:50PM (#36118524)
Fair enough :)
Re:A Terminal Case of Linux by bloopernova on Monday May 29, 2023 @05:30PM (#36118327)
After your cat command has run, type 'vim ' then hit the escape key plus the period/full stop key. That inserts the previous command's parameters/arguments at the cursor.

Obviously you don't have to use vim, any other editor or whatever can be used.

Re:A Terminal Case of Linux by quesera on Monday May 29, 2023 @05:46PM (#36118489)
> inserts the previous command's parameters/arguments at the cursor

In zsh, there are equivalent expansions:

  !!:1    previous command line, arg 1 (zero-indexed)
  !!:$    previous command line, LAST arg
  !!:1-$  previous command line, args 1-end (zero-indexed)
So, e.g.:

  cat /etc/passwd /etc/shadow /etc/group

  vi !!:1-$
(becomes)

  vi /etc/passwd /etc/shadow /etc/group
Re:A Terminal Case of Linux by bloopernova on Monday May 29, 2023 @06:10PM (#36118702)
Nice! I'll have to add those to my wall of index cards with useful commands.
Re:A Terminal Case of Linux by quesera on Monday May 29, 2023 @06:20PM (#36118776)
I use !!:$ occasionally.

If I wanted to do the cat/vim switcheroo you described, I'd more likely do:

  <UpArrow><Esc>vcwvi<Esc>:wq<Enter><Enter>
Which is a greater number of keypresses, but more flexible and requires less thought.

...as they say: Unix is user-friendly — it's just choosy about who its friends are.

Re:A Terminal Case of Linux by boring_twenties on Tuesday May 30, 2023 @03:32AM (#36122108)
Those all work in bash too, I believe they come from csh
Re:A Terminal Case of Linux by tedunangst on Monday May 29, 2023 @05:39PM (#36118409)
cat file leaves the contents on my screen as I compose my next shell command, as opposed to erasing them as quitting the editor flips back from the alt screen.
Re:A Terminal Case of Linux by quesera on Monday May 29, 2023 @05:55PM (#36118575)
I sometimes use the following prevent screen clearing when exiting vi:

  :set t_te=
Useful because vi makes it more convenient to select the chunk of file I want to view after exiting. More convenient than cat/head/tail at least. Competitive with more. :)
Re:A Terminal Case of Linux by scbrg on Tuesday May 30, 2023 @01:18AM (#36121370)
My terminal emulator has supported scrollback since I started using it in '95. I didn't get the impression at the time that it was a particularly new feature :)
Re:A Terminal Case of Linux by sverona on Wednesday May 31, 2023 @03:21PM (#36142805)
Sure, 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.
Re:A Terminal Case of Linux by vsviridov on Monday May 29, 2023 @02:01PM (#36116311)
I build pipes left to right, and I read pipes left to right...

1 -> 2 -> 3 is easier that (2 <- 1) -> 3

Re:A Terminal Case of Linux by samsquire on Monday May 29, 2023 @02:04PM (#36116353)
You 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)
Re:A Terminal Case of Linux by tolciho on Monday May 29, 2023 @02:11PM (#36116409)
Sometimes 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...

Re:A Terminal Case of Linux by kzrdude on Monday May 29, 2023 @02:26PM (#36116533)
Nice, I learned something and thank you
Re:A Terminal Case of Linux by ilyt on Monday May 29, 2023 @04:25PM (#36117694)
aliasing c to cat still requires less keystrokes
Re:A Terminal Case of Linux by antonvs on Monday May 29, 2023 @10:10PM (#36120433)
But 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.
Re:A Terminal Case of Linux by throwaway173738 on Monday May 29, 2023 @02:55PM (#36116771)
This is also the classic argument against reverse polish notation. Operator-first makes it harder to say the name of an operator in a sentence.
Re:A Terminal Case of Linux by ajuc on Monday May 29, 2023 @04:14PM (#36117608)
Reverse polish notation is operator last.
Re:A Terminal Case of Linux by eru on Monday May 29, 2023 @09:52PM (#36120333)
Operator first makes the sentence easier:

'+ 2 3' becomes 'add 2 and 3'

In any case, it's a silly objection.

Re:A Terminal Case of Linux by pxc on Tuesday May 30, 2023 @02:59AM (#36121906)
It'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!
Re:A Terminal Case of Linux by jrockway on Monday May 29, 2023 @05:10PM (#36118143)
Infix 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.)

Re:A Terminal Case of Linux by vram22 on Monday May 29, 2023 @08:03PM (#36119609)
>every elementary school student has to memorize "please excuse my dear aunt sally"

In Indian schools it used to be BODMAS, for Brackets Of Division Multiplication Addition Subtraction, for operator precedence, for which our teachers told us the mnemonic was badmaash, meaning a scoundrel or a villain, in Hindi. Guaranteed to make kids remember it. :)

Of, as in half or a quarter or ... of some other number.

Re:A Terminal Case of Linux by antonvs on Monday May 29, 2023 @10:29PM (#36120521)
> C copied this concept

I think FORTRAN copied it first. Which makes sense, because of the original scientific target market for FORTRAN, represented in its name derived from “formula translating system”. Translating “a sufficiently rich mathematical language”, as Backus put it, was an explicit goal as early as 1954.

C then (presumably) just followed the convention established by FORTRAN.

Re:A Terminal Case of Linux by somat on Monday May 29, 2023 @10:56PM (#36120662)
Unfortunately we will never get rpn taught in schools so it will always feel unnatural and weird to many people.

what is unnatural is the complicated case specific precedence rules mid notation requires. rpn still has precedence rules but because they are simple it appears that there are none and because they are universal there is no confusion as to where any new operators fit in.

I wonder if anybody has ever written a linguistic history of math notation and how it ended up the way it did.

Re:A Terminal Case of Linux by ajuc on Tuesday May 30, 2023 @03:06AM (#36121941)
Maybe it's just what I'm used to, but doing anything other than calculating the value of an expression with RPN seems hard to me.

    (x-3)(x+2)-8 > 2x^2+3
    x^2-x-8 > 2x^2+3
    x^2+x+8 < -3
    x^2+x+11 < 0
vs

    x 3 - x 2 + * 8 - x x * 2 * 3 + >
how would I simplify the expressions here? Maybe it's possible without transforming to infix but I can't do it.
Re:A Terminal Case of Linux by XorNot on Monday May 29, 2023 @09:57PM (#36120360)
Yes but it cleanly separates code and data, and notably on an interactive shell makes editing a historical command much simpler site to cursor positioning.
Re:A Terminal Case of Linux by dllthomas on Monday May 29, 2023 @03:04PM (#36116869)
These advantages are generally shared by simply opening with "<filename" instead of "cat filename |".
Re:A Terminal Case of Linux by alex_smart on Monday May 29, 2023 @03:09PM (#36116933)
I 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.

Re:A Terminal Case of Linux by arendtio on Monday May 29, 2023 @03:16PM (#36116998)
I 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 ;-)

Re:A Terminal Case of Linux by ilyt on Monday May 29, 2023 @04:24PM (#36117682)
It'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
Re:A Terminal Case of Linux by paulddraper on Monday May 29, 2023 @06:01PM (#36118638)

    < 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:

Re:A Terminal Case of Linux by gorgoiler on Monday May 29, 2023 @06:47PM (#36119013)
Not 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).
Re:A Terminal Case of Linux by somat on Monday May 29, 2023 @10:40PM (#36120585)
I 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?)

Re:A Terminal Case of Linux by AtlasBarfed on Monday May 29, 2023 @11:51PM (#36120948)
pipes 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)
Re:A Terminal Case of Linux by plq on Tuesday May 30, 2023 @03:35AM (#36122124)
> 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 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 :)

Re:A Terminal Case of Linux by yesco on Tuesday May 30, 2023 @01:54PM (#36128109)
The 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.