Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

I heard about "useless use of cat" and found some suggestions, but the following outputs nothing in my bash shell.

< filename

Using cat works as expected though.

cat filename

I'm using Fedora Core 18 and GNU bash, version 4.2.45(1).

EDIT: Using it in front of a pipe doesn't work either.

< filename | grep pattern

Whereas using cat works as expected.

cat filename | grep pattern

EDIT2: To clarify, I know that I can use this

grep pattern < filename

but I read here http://stackoverflow.com/questions/11710552/useless-use-of-cat that I can also use it in front of the command. It does not work in front of the command though.

share|improve this question
1  
It works. Just what you tried is not the same as Jonathan Leffler's comment suggests. –  manatwork Dec 20 '13 at 14:23
    
"The purpose of cat is to concatenate (or "catenate") files. If it's only one file, concatenating it with nothing at all is a waste of time, and costs you a process." partmaps.org/era/unix/award.html –  Bonsi Scott Dec 21 '13 at 8:31

3 Answers 3

up vote 12 down vote accepted

The less than and symbol (<) is opening the file up and attaching it to the standard input device handle of some application/program. But you haven't given the shell any application to attach the input to.

Example

These 2 examples do essentially the same thing but get their input in 2 slightly different manners.

opens file

$ cat blah.txt 
hi

opens STDIN

$ cat < blah.txt 
hi

Peeking behind the curtain

You can use strace to see what's going on.

When we read from a file

open("blah.txt", O_RDONLY)              = 3
fstat(3, {st_mode=S_IFREG|0664, st_size=3, ...}) = 0
fadvise64(3, 0, 0, POSIX_FADV_SEQUENTIAL) = 0
read(3, "hi\n", 65536)                  = 3
write(1, "hi\n", 3hi
)                     = 3
read(3, "", 65536)                      = 0
close(3)                                = 0
close(1)                                = 0

When we read from STDIN (identified as 0)

read(0, "hi\n", 65536)                  = 3
write(1, "hi\n", 3hi
)                     = 3
read(0, "", 65536)                      = 0
close(0)                                = 0
close(1)                                = 0

In the first example we can see that cat opened the file and read from it, blah.txt. In the second we can see that cat reads the contents of the file blah.txt via the STDIN file descriptor, identified as descriptor number 0.

read(0, "hi\n", 65536)                  = 3
share|improve this answer
1  
So this talk about useless use of cat is bogus? –  bug Dec 20 '13 at 14:13
    
@bug - no, there are uses. But cat is generally misunderstood and is used when it isn't necessary. –  slm Dec 20 '13 at 14:14
    
But it is necessary when I want to preserve the order of the operations from left to right? I read that it is possible to use the less-than construct in front of the command as well. –  bug Dec 20 '13 at 14:15
    
@bug yes the redirect can occur before or after the command, see Stephane's answer, he shows this example as well. –  slm Dec 20 '13 at 14:20
    
Ah, now I get it. I'd have to write < filename command. –  bug Dec 20 '13 at 14:25

The UUOC is in:

cat somefile | some-cmd

or

cat < somefile | some-cmd

There, some-cmd is reading the content of somefile from a pipe that is fed by cat which itself reads it from somefile.

some-cmd can read directly from somefile (after the shell has opened it for it on stdin), there's no need for cat:

some-cmd < somefile

or

< somefile some-cmd

(redirections can appear anywhere on a simple command line).

share|improve this answer

The classic useless use of cat is when you use it to give input to programs that are perfectly capable of opening files directly. For example:

Bad

cat file | grep foo
cat file | while read line; do echo "$line"; done
cat file | sed 's/a/b/'
cat file | awk '{print $1}'

Good

grep foo file
while read line; do echo "$line"; done < file 
sed 's/a/b/' file
awk '{print $1}' file

Also good (the <file can be on either side of the command)

<file grep foo
 sed 's/a/b/' < file
<file awk '{print $1}' 
share|improve this answer
1  
"Bad" is subjective here. I find those to be better overall, because it is way more consistent and easier to read. And the flow of data is fully left-to-right, as it should be if there's more pipes involved –  Izkata Dec 21 '13 at 9:34
1  
@Izkata they're "bad" in the sense that they are useless uses of cat. –  terdon Dec 21 '13 at 19:40
    
“Down!   Get off the table!  You’re a bad cat!”  ;-)    But seriously … –  G-Man 2 days ago
    
Noteworthy good (or, at least, useful) uses of cat include  (1) cat file (with output to the screen/terminal; although, if the file is longer than the screen is high, you might prefer to use more or less or something like that),  (2) cat file1 file2 file3 > all_data (exactly what cat is meant for),  (3) cat f1 f2 f3 | tr … (or pipe into any other program that you don’t want to pass the files to directly; e.g., wc (e.g., if you want to see the grand total only) or grep (e.g., if you have an old version that doesn’t support -h, i.e., --no-filename)),  … (Cont’d) –  G-Man 2 days ago
    
(Cont’d) …  (4) cat -n file | sort … -k1 | sed 's/^ *[0-9]*\t//',  (5) sudo cat file600 | untrusted_program (i.e., you (your UID) can’t read the file, and you don’t want to run the program as root or even any semi-privileged UID).  Also, (e) (i.e., a number between 2 and 3) program_that_generates_html | cat static_html_header - static_html_footer (which you would probably want to redirect to a file or a pipe). –  G-Man 2 days ago

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.