Why does the less-than sign not work as a replacement for cat in bash?
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 https://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.
Answers:
Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.
Method 1
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, "hin", 65536) = 3 write(1, "hin", 3hi ) = 3 read(3, "", 65536) = 0 close(3) = 0 close(1) = 0
When we read from STDIN (identified as 0)
read(0, "hin", 65536) = 3 write(1, "hin", 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, "hin", 65536) = 3
Method 2
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}'
Method 3
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).
All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0