Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

For some reason I never liked to do it the "right way". First of all it doesn't seem to actually matter.

But most of all the cat way just aligns with my mental model more. Data flows left to right, if you catch my drift.

It also makes it easier to add arguments to the end if re-running it.



Besides it's also a fail-safe way to make sure the program doesn't modify the original file.

    random-app ./myfile.txt 
The app opens the file on its own. It could decide to write to it.

    cat ./myfile.txt | random-app
The app receives chunks of the file from a pipe. It doesn't know where the original file is.

This is especially useful if you aren't sure the program will by default modify the file (such as formatters).


Yeah but you get the same from

    random-app < ./myfile.txt


Only if random-app is well-behaved (and if you knew it was you could just use `random-app ./myfile.txt`).

  $ echo foo > a.txt
  $ <a.txt ( echo bar >/proc/self/fd/0 )
  $ cat a.txt
  bar


That's bizarre and perverse! Surely someone has brought it up as a bug before that stdin is read-write! Is there some Posix standard preventing the standard shells from opening stdin as read-only???


stdin is readonly. `<a.txt ls /proc/self/fd/0` generally gives 'lr-x------' for the permissions. The problem is that having a open file descriptor to a file lets a program get and/or act-as-if-it-had a path to the file; /proc/self/fd/ is just the easiest way to do that.


So the thing is that this is a nothingburger. Just because you gave a pathname to an untrusted app means nothing. You've already trusted the app with your user account. It could already overwrite or vandalize that file no matter how you invoked it. Just because you indicate that file is special to you doesn't change anything in the threat model here. For all you know, the app could just traverse the entire directory tree and trash every file it could possibly write to, or just confine the damage to your $HOME.

There's no reason IMHO to avoid using a file as an argument, or directly as stdin. If you don't trust an app, don't run it in your user account; you run it in a sandbox, right? This is 2023.

Now a case could be made for defending against misbehavior by an app that might write to an fd by mistake, but as a1369209993 demonstrates, writing to stdin is a very deliberate choice, as you'll need to look up a pathname and deliberately open that file as writable. That's not misbehavior, that's malice, and that doesn't belong anywhere near your user account in the first place.


Ah, I believe I see what's happening there.

So, hiding the pathname from an untrusted tool via an unnamed pipe is a Posix security measure. Still bizarre!

Who was the guy who awarded UUOC prizes? Wasn't he a real dyed-in-the-wool security wonk?


>But most of all the cat way just aligns with my mental model more. Data flows left to right, if you catch my drift.

Using `<` doesn't change that model. You can write `< somefile.txt whatever`. I always write my commandlines as `<in_file cmd1 | cmd2 | cmd3 >out_file`

(Though annoyingly this doesn't work for feeding input to while loops. `< <(echo a; echo b; echo c;) while read -r foo; do echo "$foo"; done` is invalid syntax; it needs to be `while read -r foo; do echo "$foo"; done < <(echo a; echo b; echo c;)`)


> Using `<` doesn't change that model. You can write `< somefile.txt whatever`.

If you showed that without context it would look like some prefix/lispy notation so no, you are just showing how bad it is


"This thing I don't understand reminds me of another thing I don't understand, so it's bad I decided."


[flagged]


I thought it was an informative response. I certainly learned some stuff about shell I didn't know before. I'm still gonna use cat because it's simpler to me.

I think your snark is unfounded here.


doesn't it work if you put it after the while but before the read?


No. That will execute `< <(...) read` anew for every loop iteration, which in this case will cause it to print an endless stream of `a`s.


I share the same opinion, I was made fun of with the "useless use of cat award" but find it so convienent to cat | grep then cat | grep | awk | wc then whatever with data flowing left to right and modifying the command sequence as I explore the file content.


While I get your point...

> It also makes it easier to add arguments to the end if re-running it.

I'd like to point out that a redirection doesn't have to be the last thing in a command. E.g. the common 'echo >&2 "some message"' works fine.


Quite. I had occasion to share this[0] in another thread, and it's relevant here, too:

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

[0] https://stackoverflow.com/a/16619430/1040915




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: