0

I was trying bash shell redirection. I have a directory where there is just one file - a.txt

more a.txt
HELLO

If I type cat < a.txt b.txt , I get

cat: b.txt: No such file or directory

If I type

cat  < a.txt   b.txt a.txt

I get

cat: b.txt: No such file or directory
HELLO

Why am I not seeing HELLO when I try cat < a.txt b.txt? I tried different combinations - typing a.txt multiple times before/after b.txt and see a pattern, but not able to figure out why.

cat  <   a.txt a.txt b.txt  
HELLO
cat: b.txt: No such file or directory
1
  • cat is a program, not something built into Linux. In many cases, it's from GNU, though I could imagine busybox also providing one. Consider fixing that in the title and also removing the "linux" tag, see its description for more. Further, it's not "linux redirection" but a shell feature. Most likely it's ash or bash in your case, but it could also be a different shell. Again, see the description of the "shell" tag why it's usually wrong. Commented Jan 29, 2022 at 9:10

3 Answers 3

1

I assume you don't use cat the right way. Cat expects a file or many files as parameter not an data stream.

To show the file with cat use:

cat a.txt

To Redirect it into file b.txt

cat a.txt > b.txt

And your last question, with the pattern.

You pass 3 arguments to cat.

Arg1: (< a.txt) Arg2: (a.txt) Arg3: (b.txt)

Argument 1 is nonsense Argument 2 a valid file and Arg 3 an incorrect file.

Sign up to request clarification or add additional context in comments.

2 Comments

I usually use cat command the way you have shown. I was just trying simple redirection options for stdout, stderr and observed this behaviour, and got curious.
It works with less, and more but not with cat cause, as explained cat expects an filepath. Less and more might also handle file paths but can display data streams as well.
0

Redirecting means sending the content of the file into the command's STDIN.

cat's behavior is to read content of file in it's argument(s) to STDOUT. But if there's no argument, then the content is read from STDIN.

See that I write argument(s) there? It's because the number of argument can be 0, 1, or multiple.

in simple pseudocode, it's like this:

if number of arguments = 0
  print STDIN to STDOUT
else
  for each file in arguments
    print file content to STDOUT

Example 1:

cat a.txt

output:

HELLO

Example 2:

cat (then enter)

You will be able to type into terminal, when you click enter, the typed line is sent to cat's STDIN. Then cat will print line you just typed.

Answer

So when you type:

cat < a.txt b.txt

internally, it works like this:

  • STDIN is filled with content of a.txt HELLO text
  • $1 (first argument) is b.txt which is a non-existent file

based on behavior above, it will print content of b.txt alone since there is 1 argument supplied.

but it doesn't find file b.txt, so it outputs an error message.

when you type:

cat < a.txt b.txt a.txt

internally, it works like this:

  • STDIN is filled with content of a.txt HELLO text
  • $1 (first argument) is b.txt which is a non-existent file
  • $2 (second argument) is a.txt

will output: (once again STDIN is ignored because there are 2 arguments)

cat: b.txt: No such file or directory
HELLO

More detailed explanation

  • when you run command mycommand arg1 arg2 arg3, it means there are 3 command line arguments: arg1, arg2, arg3 respectively
  • STDIN is standard input: data stream for sending input to a command. You can send data to STDIN like these (assuming the target command is cat):
    • echo "my data" | cat
    • make file called data.txt, filled with my data, save it, then use cat < data.txt

Comments

0

< inputfile is a redirection. < redirects the file inputfile into stdin standard input of a command. The < and inputfile are not passed as arguments to the command. The placement doesn't matter, these lines are all exactly the same:

< inputfile command arg1 arg2
command < inputfile arg1 arg2
command arg1 < inputfile arg2
command arg1 arg2 < inputfile

Why am I not seeing HELLO when I try cat < a.txt b.txt?

From man cat:

 With no FILE, or when FILE is -, read standard input.

Because given arguments, cat is not reading from stdin - stdin is ignored. Instead it reads from given FILEs on arguments. So a.txt on stdin is ignored.

You can do:

< a.txt cat - b.txt
# or
cat - < a.txt b.txt
# or
cat - b.txt < a.txt
# or really just
cat a.txt b.txt

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.