cat is misunderstood a lot. The purpose of cat is to combine multiple files together (it's literally short for "concatenate"), like cat *.log to combine all log files together.
If you're just using it for a single file, then you should just redirect the file to stdin. These two command lines behave similarly:
cat foo.txt | some-command
some-command < foo.txt
For head, tail, grep and some other commands, you can just pass in the file name directly as an argument (e.g. grep whatever foo.txt).
You'll see cat FILE | all the time because it's just a natural start to a pipeline. You cat FILE to see the content unfiltered before filtering it with further commands.
I still like doing cat file.txt | grep thing because I often re-run it to find something else like cat file.txt | grep thing2 - and if I do that with grep, the pattern sits awkwardly in the middle instead of at the end
That's fair. I'd usually just use less and drop to the end. My use cases would always need the older log before a newer log though because that's the start of the problem. At least that's how I operate.
it'll wait for you to type ten lines (the default for head without arguments), buffer them (bc tail must buffer its input), then spit them back at you, and exit
head takes the first N lines of its input (if -n <number> is not specified, the default is 10 lines, and default reading from stdin, which in this case is your terminal) and prints them to its stdout (which thanks to the pipe, goes directly to cat's stdin), then signals end-of-file.
cat accepts any number of filenames and conCATenates them (hence the name), writing their contents one after the other to stdout. with only one file as argument (the most common case in practice) it will simply write that file's contents to stdout. with no arguments (as in this case) it will simply copy everything from its stdin (in this case head's stdout) to its stdout (in this case tail's stdin). the cat command could be completely omitted from this invocation (leaving simply head | tail) and it would work exactly the same.
tail reads its entire input (like head, it defaults to reading from stdin unless a filename is specified) and buffers it, then, when the end of the file is reached, it prints the last N lines is read (again defaulting to 10 unless -n <number> is specified) to stdout (in this case your terminal).
put all together, head will wait for you to type a line, then will pass it on to cat, which will then immediately pass it on to tail, which will add it to a buffer and wait for another line. rinse and repeat until you have typed 10 lines, and then head will exit and the pipe between it and cat will close. cat, noticing the closed pipe, will exit in turn, causing the pipe between it and tail to close. tail, seeing an end of file signal on its input pipe, will cough up the last 10 lines in its buffer and then exit. since head only sent it 10 lines, this is the entirety of its input. so it will spit back everything you typed.
If you press Ctrl+D to send head an end-of-file signal before you have typed 10 lines, head will exit immediately, causing cat to exit, causing tail to output everything it had in its buffer so far.
For the past 30 years or so, my brain always tells me to type "last" instead of "tail". This usually results in some kind of "Permission denied" message that confuses me for a few seconds.
Yes, but it shows information about recent/current logins and requires access a file called wtmp (or something like that, off the top of my head), and that requires privileged access.
My usual use case where I mix it up is looking at a log file and and I just want to see the last few entries. So my brain 🧠 tells my fingers to type "last logfile", and when I get the permission message it tells my mouth to go, "Doh!".
69 Comments
dan@upvote.au · 85 pts · 32d
catis misunderstood a lot. The purpose of cat is to combine multiple files together (it's literally short for "concatenate"), likecat *.logto combine all log files together.If you're just using it for a single file, then you should just redirect the file to stdin. These two command lines behave similarly:
For
head,tail,grepand some other commands, you can just pass in the file name directly as an argument (e.g.grep whatever foo.txt).pedz@lemmy.ca · 75 pts · 32d
Also known as cat abuse.
shark_byte@lemmy.zip · 18 pts · 32d
awww what's a cat without a head and a tail?
ranzispa@mander.xyz · 11 pts · 31d
I guess depending on your interpretation of without it could either be "cat" or "a".
MonkderVierte@lemmy.zip · 9 pts · 32d
A kernel?
shark_byte@lemmy.zip · 7 pts · 32d
uhmm no
lokalhorst@feddit.org · 17 pts · 32d
If I just want to look at the file, is there a better way than
cat foo.txt? I guess I can't just do< foo.txtmote@lemmy.ca · 22 pts · 32d
So close! you have to do
cat < foo.txt:-) (/s)dan@upvote.au · 13 pts · 31d
Admittedly I still use
catfor this.This also works too, but it's more verbose:
It's mentioned in the Bash man pages:
EDIT: I was just informed that simply
<foo.txtworks too.not_IO@lemmy.blahaj.zone · 6 pts · 31d
how in the world is this not a useless use of echo and equivalent to
<foo.txtdan@upvote.au · 6 pts · 31d
OK, TIL you can just do
<foo.txt. I didn't think that worked. Thanks!not_IO@lemmy.blahaj.zone · 2 pts · 28d
i don't think you can but idk why that's by I'm asking
TwilightKiddy@scribe.disroot.org · 4 pts · 31d
You can use
less. There are also specialized ones for that purpose like bat.MonkeMischief@lemmy.today · 1 pts · 30d
If it's really long, I use
less, because it breaks it up into navigable pages instead of filling your entire buffer. :)Never knew about just using < though! Cool!
shark_byte@lemmy.zip · 15 pts · 32d
yeah sure but the command is literally written for the humor.
dan@upvote.au · 18 pts · 32d
I know, but I just wanted to mention this since a lot of new Linux users end up using cat this way :)
shark_byte@lemmy.zip · 4 pts · 32d
ohhh but it's all humor that's the point of the post.
I mean as a new Linux user, I won't take anything from a humor group seriously.
daychilde@lemmy.world · 2 pts · 31d
I would.
I'd be careful of jokes, sure, but geeks often can't help have real discussions. Like in this very thread
Grail@multiverse.soulism.net · 4 pts · 31d
Is there any downside?
sqw@lemmy.sdf.org · 2 pts · 31d
qqq@lemmy.world · 15 pts · 31d
You'll see
cat FILE |all the time because it's just a natural start to a pipeline. Youcat FILEto see the content unfiltered before filtering it with further commands.BasedMaquisEddington@lemmy.dbzer0.com · 17 pts · 31d
ranzispa@mander.xyz · 11 pts · 31d
Fair, but in general I find it way more useful to use cat for piping.
In most cases I'll do something like
This gets more complicated if the file is at the end of the command.
dan@upvote.au · 8 pts · 31d
It wouldn't be at the end, since you'd still be piping into
programjxk@sh.itjust.works · 14 pts · 31d
And
<file program | grep | cutworks tooranzispa@mander.xyz · 3 pts · 31d
Oh, thanks! Didn't know that
dan@upvote.au · 1 pts · 31d
Thanks - I didn't know this either!
Digit@lemmy.today · 1 pts · 27d
These
<filethings must be for different shells than the ones I use.a_non_monotonic_function@lemmy.world · 1 pts · 30d
I don't know why anybody would disagree with this. It's a very clean way of putting it.
eager_eagle@lemmy.world · 10 pts · 31d
I still like doing
cat file.txt | grep thingbecause I often re-run it to find something else likecat file.txt | grep thing2- and if I do that with grep, the pattern sits awkwardly in the middle instead of at the endtgt@programming.dev · 9 pts · 31d
< file.txt grep thingalso works.sqw@lemmy.sdf.org · 2 pts · 31d
is it more obtuse
A_norny_mousse@piefed.zip · 29 pts · 32d
Another all-time favorite:
TwilightKiddy@scribe.disroot.org · 20 pts · 31d
Digit@lemmy.today · 1 pts · 27d
Huh. ... I could have swore there was a woman. I even package searched, even in overlays... no woman.
No woman.
No cry.
red_tomato@lemmy.world · 22 pts · 32d
tacis a cat but faced the other wayshark_byte@lemmy.zip · 12 pts · 32d
ohhh let me check it out lol
exu@feditown.com · 15 pts · 32d
I've been using a slightly customized bash-cat for years now. Still makes me smile when I see it
shark_byte@lemmy.zip · 5 pts · 32d
yeah I just checked it out it's cute
A_norny_mousse@piefed.zip · 2 pts · 31d
last commit message: "Shorter Cat with added Tail." 👍
anotherspinelessdem@lemmy.ml · 12 pts · 32d
darth_grunkus@lemmy.world · 14 pts · 31d
rumba@lemmy.zip · 11 pts · 31d
tac
Sprocketfree@sh.itjust.works · 4 pts · 31d
I've always wondered what a good use case for tac would be...
rumba@lemmy.zip · 4 pts · 31d
Reverse chronological order, mostly
tac log.txt |head # would give you newest first
no good for sort because sort already supports -r
no need it for tail on large files because tail already skips to the end.
I do a lot of impromptu bash to sus crap out of logs.
when you're balls deep in
cat log|grep -v foo| rev|cut -f 1-3 -d \ | |rev
Sometimes tac comes in clutch.
Sprocketfree@sh.itjust.works · 4 pts · 31d
That's fair. I'd usually just use less and drop to the end. My use cases would always need the older log before a newer log though because that's the start of the problem. At least that's how I operate.
Jankatarch@lemmy.world · 10 pts · 31d
Bat is my favorite command to date.
shark_byte@lemmy.zip · 8 pts · 31d
Digit@lemmy.today · 1 pts · 27d
man bat | batDyskolos@lemmy.zip · 10 pts · 31d
I was today's years old to finally notice the cat-head-tail thing...
But it also just recently dawned upon me why pacman has those weird "c" as progress indicators...
I'm not a smart man...
TwilightKiddy@scribe.disroot.org · 9 pts · 31d
I always thought it's
It, of course, waits for an input, which brings up the one and only question...
Have you fed your cat?
shark_byte@lemmy.zip · 6 pts · 31d
of course look meow meow so loud
Digit@lemmy.today · 1 pts · 27d
I'm scared to run that.
Is that like some kind of fork bomb?
Or is it just a tubular cat?
TwilightKiddy@scribe.disroot.org · 3 pts · 27d
Put suspicious cats into sandboxes until it's proven that they are crewmates.
AVincentInSpace@pawb.social · 2 pts · 25d
it won't... do anything
it'll wait for you to type ten lines (the default for
headwithout arguments), buffer them (bctailmust buffer its input), then spit them back at you, and exitheadtakes the first N lines of its input (if-n <number>is not specified, the default is 10 lines, and default reading from stdin, which in this case is your terminal) and prints them to its stdout (which thanks to the pipe, goes directly tocat's stdin), then signals end-of-file.cataccepts any number of filenames and conCATenates them (hence the name), writing their contents one after the other to stdout. with only one file as argument (the most common case in practice) it will simply write that file's contents to stdout. with no arguments (as in this case) it will simply copy everything from its stdin (in this casehead's stdout) to its stdout (in this casetail's stdin). thecatcommand could be completely omitted from this invocation (leaving simplyhead | tail) and it would work exactly the same.tailreads its entire input (likehead, it defaults to reading from stdin unless a filename is specified) and buffers it, then, when the end of the file is reached, it prints the last N lines is read (again defaulting to 10 unless-n <number>is specified) to stdout (in this case your terminal).put all together,
headwill wait for you to type a line, then will pass it on tocat, which will then immediately pass it on totail, which will add it to a buffer and wait for another line. rinse and repeat until you have typed 10 lines, and thenheadwill exit and the pipe between it andcatwill close.cat, noticing the closed pipe, will exit in turn, causing the pipe between it andtailto close.tail, seeing an end of file signal on its input pipe, will cough up the last 10 lines in its buffer and then exit. sinceheadonly sent it 10 lines, this is the entirety of its input. so it will spit back everything you typed.If you press Ctrl+D to send
headan end-of-file signal before you have typed 10 lines,headwill exit immediately, causingcatto exit, causingtailto output everything it had in its buffer so far.HamsterRage@lemmy.ca · 7 pts · 31d
For the past 30 years or so, my brain always tells me to type "last" instead of "tail". This usually results in some kind of "Permission denied" message that confuses me for a few seconds.
shark_byte@lemmy.zip · 1 pts · 31d
there's a last command? just knowing that.
HamsterRage@lemmy.ca · 4 pts · 30d
Yes, but it shows information about recent/current logins and requires access a file called wtmp (or something like that, off the top of my head), and that requires privileged access.
My usual use case where I mix it up is looking at a log file and and I just want to see the last few entries. So my brain 🧠 tells my fingers to type "last logfile", and when I get the permission message it tells my mouth to go, "Doh!".
shark_byte@lemmy.zip · 2 pts · 30d
yeah I looked it up
this will be handy
Avicenna@programming.dev · 7 pts · 31d
whereis cat?
LedgeDrop@lemmy.zip · 11 pts · 31d
which catAvicenna@programming.dev · 6 pts · 31d
whatis cat?
cypherpunks@lemmy.ml · 9 pts · 31d
man catAvicenna@programming.dev · 5 pts · 31d
locate cat
cypherpunks@lemmy.ml · 3 pts · 30d
strace catreader@lemmy.zip · 5 pts · 31d
rtfm
selarian@lemmy.world · 1 pts · 31d
Be careful now, 2000/2010 Linux terminology can be taken as an insult in 2026. /s
I’m tired of this stupid coddling bullshit with the influx of new Linux users. If you can’t read don’t use Linux. Simple. 😂
piccolo@sh.itjust.works · 2 pts · 31d
But wheres the manual??
MonkeMischief@lemmy.today · 1 pts · 30d
In order of approachability:
Man pages.
Also Arch Wiki.
Also excellent books by NoStarch Press.
... Or did I miss a joke? Hehe
Digit@lemmy.today · 1 pts · 27d
Missing the joke is always worthy as it's own joke.