What is the difference between "cat < filename" and "cat filename"?
cat file
The cat
program will open, read and close the file.
cat < file
Your shell will open the file and connect the contents to cat
's stdin. cat
recognizes it has no file arguments, and will read from stdin.
There is no difference from a user point of view. These commands do the same thing.
Technically the difference is in what program opens the file: the cat
program or the shell that runs it. Redirections are set up by the shell, before it runs a command.
(So in some other commands--that is, not the command shown in the question--there may be a difference. In particular, if you can't access file.txt
but the root user can, then sudo cat file.txt
works but sudo cat < file.txt
does not.)
You can use either one that is convenient in your case.
There are almost always many ways to get the same result.
cat
accepts a file from arguments or stdin
if there are no arguments.
See man cat
:
SYNOPSIS
cat [OPTION]... [FILE]...
DESCRIPTION
Concatenate FILE(s) to standard output.
With no FILE, or when FILE is -, read standard input.
One Big Difference
One big difference is with the *
, ?
, or [
globbing characters (wildcards) or anything else the shell may expand into multiple filenames. Anything the shell expands into two or more items, rather than treating as a single filename, cannot be opened for redirection.
Without redirection (ie no <
), the shell passes multiple filenames to cat
, which outputs the files' contents one after another. For example this works:
$ ls hello?.py
hello1.py hello2.py
$ cat hello?.py
# Output for two files 'hello1.py' and 'hello2.py' appear on your screen
But with redirection (<
) an error message occurs:
$ ls < hello?.py
bash: hello?.py: ambiguous redirect
$ cat < hello?.py
bash: hello?.py: ambiguous redirect
One Tiny Difference
I thought with redirection it would be slower but there is no perceivable time difference:
$ time for f in * ; do cat "$f" > /dev/null ; done
real 0m3.399s
user 0m0.130s
sys 0m1.940s
$ time for f in * ; do cat < "$f" > /dev/null ; done
real 0m3.430s
user 0m0.100s
sys 0m2.043s
Notes:
- The difference is about 1/1000th (1 one thousandth) of a second in this test. In other tests it was 1/100th of a second which is still can't be noticed.
- Alternate the tests a few times so data is cached into RAM as much as possible and more consistent comparison times are returned. Another option is to drop all caches before each test.