8 ms·
if you prefer to use cat just to read your pipeline from left to right, you can just start your command with file redirection. It doesn't have to be at the end
by codesnik 2y ago
if you prefer to use cat just to read your pipeline from left to right, you can just start your command with file redirection. It doesn't have to be at the end of the command.
<file grep something | do something else ...
this works in bash too, but if you're using zsh, there're a couple of nice shortcuts
<file
on it's own works as
more file
and
> file
...
...
^D
allows you to put something into the file quickly without firing up the editor. Though
> file << end
...
end
will give you nicer line editing experience.
more zsh redirection tricks here: https://zsh.sourceforge.io/Doc/Release/Redirection.html#Multios https://zsh.sourceforge.io/Doc/Release/Redirection.html#Mult...
- globular-toast 2y agoIf I saw <file grep ... It would give me pause. If I saw cat file | grep ... I would understand it instantly, as would any other Unix user. Therefore the latter is better code.
- CBLT 2y agoI don't feel <file is obscure. I've seen shell in that style from coworkers and from open source. Your value judgement against it might just be your experience, rather than something universal.
- sgarland 2y agoOr just use grep <pattern> file?
- pastage 2y agoThe point is you do not know if file is a stream, an archive, too big, currently empty or just contains bad data for your current test. So using cat file is a way to standardize debugging or make development easier.
- cellularmitosis 2y agoAlso, you can replace cat with pv to get a progress bar. Or replace cat with socat to stream stdin from a network socket. Etc etc.
- zahlman 2y ago`<file` at the start might not be idiomatic, but when I see it I think it makes perfect sense. It puts the pipeline "in order", starting with redirection from the input (and presumably ending with redirection to the output, if not stdout).
- HappMacDonald 2y agoI usually interpret `command <fileA >fileB` as meaning "shove fileA into this command, and shove output into fileB". The "arrows" make visual sense this way. `<fileA command` OTOH at least visually gives off the impression that it's sending the command's output to the left (changing the prompt, perhaps?)
- oneeyedpigeon 2y agoIf only we could do `fileA> command >fileb` for the ultimate readability...
- crdrost 2y agoThe problem is that according to this argument `cat` should never be used for the thing it was designed for, because if you use it with more than one argument, it would give most Unix users pause, but if you saw it with only one argument they would understand it instantly. The whole point of the "never use cat" Unix advice is a war between instrumentalism and design purism. Should things be known mostly for what they're useful for, or mostly for what they were made to do? If you understand this, then the war is not soluble but you can at least phrase a third position that will reconcile both sides. If you don't understand this, then the war is over an issue that doesn't even exist. Hot take: `<file> | abc` and `abc | <file>` should both make sense because a file should be understood by default as a command that reads from and writes to a particular destination, and the shell should take it seriously that `abc | <file>` needs to be easily undoable if the file wasn't chmodded +x appropriately.
- deleted 2y ago[deleted]
- makapuf 2y agoWhat if you want to grep a bash script file?
- pastage 2y agoCan you explain what fou mean by <file> | abc? I have no clue what that would mean. Further what does undoable mean in a shell context?
- oktoberpaard 2y agoSo `abc | <file>` would write the stdout of `abc` to the file? Meaning that if you forgot to mark your script as executable, you’ve now lost all your work? I think `abc > <file>` works perfectly fine and pipes don’t need to substitute this behavior.
- crdrost 2y agoThat's the point is that it's up to the shell to make sure that you don't use your work if you do the wrong thing. Could be as simple as prompting you to make sure -- "Overwrite <filename>? [yn]: " -- or could be something where the old inode is still available under some magic path for a few more commands, or could be that you use special syntax for the command, like "@<path>" is the stdin/stdout command form for the path... or it could be something else entirely, really. For an instance where there are thousands of bash scripts out there that work around a case where `abc >file` does not work, consider the times when you want to write to a file which you don't have write permissions to, with sudo. my favorite way to do this is with `tee` but I have also seen others: but `>file` is not one of them! Because it's emphatically not part of the algebra of the rest of the shell; the rest of the shell is written in pipes, this one command says "I'm going to make your pipeline terminate, this step will be un-pipeable." For another example where the algebra doesn't consistently handle the whole system, consider that in a normal language you would consider writing a function which returns a value and also prints debug logs to the process's stdout. Bash can't do this on its own, you have to figure out which /dev/tty is attached to the process and then write your debug log to that TTY, and then your script probably fails in interesting ways when it itself is redirected to a file and there is no TTY that it is attached to anymore...
- AStonesThrow 2y agoBoth of those invocations would give me pause, because grep is a command that can handle file arguments on its own; in fact it can incorporate knowledge of those filenames into its output quite usefully, so I would generally avoid redirects into grep when I could use it to explicitly, directly, open the files in question.
- DevilStuff 2y agoBetter code, yeah I agree. It's way more easily understandable. At least for me though, 99% of my bash use is stuff that will never be seen by anyone else, so the simpler keystrokes one may prove useful. Maybe if I get used to it :)
- MathMonkeyMan 2y agoMy coworker said the same thing. But now that you know, will it give you pause? Shell has tricky and arcane corners that are best to avoid, but you still do better to know about them, lest they bite you (shellcheck helps). I don't think that "I/O redirection can precede the command name" is particularly tricky or arcane. What bothers me is that it doesn't work with loops: <input.txt while read -r line; do thing; done # error while read -r line; do thing; done <input.txt # fine The shell's grammar is quite a thing.
- cellularmitosis 2y ago“Subsetting” a language is a useful practice. Consider the set of language features someone has to know in order to understand your code. If you can make that set smaller (without unreasonably sacrificing functionality), you lower the barrier to entry. More people can read your code. The typical retort I hear is “but it’s just this one feature, how hard is it to learn just one feature?” But you’re only considering your favorite feature. To the casual code reader, it isn’t just that one feature, it’s everyone else’s favorite obscure feature as well. Using cat makes your code readable to a wider audience. Using cat has real upside with no downside. Forcing your readers to learn more shell syntax has real downside with no practical upside.
- MathMonkeyMan 2y agoYou make good points. The only part I disagree with is "forcing your readers to learn more shell syntax." Who am I to say what the reader does or doesn't know about the shell? I don't even know what I don't know about the shell. The language is a minefield. I always have to look up the rules for how prefix/suffix substitution works, or the finer points of heredocs, or just when exactly something should be quoted, or the precedence of boolean operators, or the difference between "[" and "test", or ... Yes, let's be considerate and not use these features. But then we must agree on the specifics of the subset. If we're going to do that, then let's just learn the language proper instead. Or, avoid shell scripts entirely. Maybe there's an analogy with writing prose. I _could_ use rare words and uncommon syntax, but the modern style is a better approach. Is "abstruse" a rare word? Will a reader be frustrated to necessarily learn about split infinitives? What about I/O redirection at the beginning of a command?
- latexr 2y agoBy that argument, no one would ever learn anything. Everything in programming is new to someone at some point. There are useful features few people know about, and you get them to be widespread and familiar by using and talking about them. Just because you only ever learned about `for` loops doesn’t mean you shouldn’t understand and use `map`.
- chgs 2y agoOr you could just use cat
- mingus88 2y agoCoward, use `tail -c +0` like the rest of us useless command cowboys
- seba_dos1 2y agoIt's actually very useful when used with wildcards/multiple arguments!
- kazinator 2y agocat file|grep x <file grep x grep x file The two alternatives are several keystrokes less and remove a useless process.
- gorgoiler 2y agoIt’s shell specific though, just like using FOO=bar cmd prefixing to make environment changes. Better to use env(1) and keep everything rooted in Unix processes rather than shell syntax, imho. # bashisms <file tr z-o m-g | … FOO=bar python3 … # processes cat file | tr z-o m-g | … env FOO=bar python3 …
- shiomiru 2y agoFile redirection is specified in POSIX: https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_07 https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V... So is FOO=bar cmd. (I guess it is shell-specific if you include csh in the game, but then what isn't...)
- MathMonkeyMan 2y agoBoth of the features that you mention are specified in POSIX, which means that bash, ksh, zsh, sh, ash, dash, etc. implement them. I find myself googling "OpenGroup shell command language" pretty often to check this sort of thing.