Cat command and echo
Solution 1
It does not work because the cat
program in your pipe sequence was not instructed to read the echo
program's output from standard input.
You can use -
as a pseudo file name to indicate standard input to cat
.
From man cat
on an msys2 installation:
EXAMPLES
cat f - g
Output f's contents, then standard input, then g's contents.
So try
echo "abc" | cat - 1.txt > 2.txt
instead.
Solution 2
As noted by others, your original command fails because cat 1.txt
disregards its standard input. Either indicate that it should be its first argument (cat - 1.txt
), or use block redirection to redirect echo abc
and cat 1.txt
together. To wit:
{ echo abc; cat 1.txt; } > 2.txt
Relevant excerpt from the manual (man bash
):
Compound Commands
A compound command is one of the following. In most cases a list in a command's description may be separated from the rest of the command by one or more newlines, and may be followed by a newline in place of a semicolon.
(
list)
list is executed in a subshell environment (see COMMAND EXECUTION ENVIRONMENT below). Variable assignments and builtin commands that affect the shell's environment do not remain in effect after the command completes. The return status is the exit status of list.
{
list;
}
list is simply executed in the current shell environment. list must be terminated with a newline or semicolon. This is known as a group command. The return status is the exit status of list. Note that unlike the metacharacters
(
and)
,{
and}
are reserved words and must occur where a reserved word is permitted to be recognized. Since they do not cause a word break, they must be separated from list by whitespace or another shell metacharacter.
The first option (subshell environment) has a bunch of side effects, most if not all of which are irrelevant to your scenario; however, if redirecting a bunch of commands' output is all you need, then Option #2 here (group command) is preferred.
Solution 3
( echo "abc"; cat 1.txt ) > 2.txt
You piped the echo output to cat, but cat had no use for input, and ignored it. Now the commands run one after the other, and their output is grouped (the parentheses) and directed into 2.txt.
Solution 4
Your command cat 1.txt
doesn't do anything with the output of echo "abc"
.
Instead:
(echo "abc"; cat 1.txt) > 2.txt
will write the output of both commands into 2.txt.
Solution 5
In any POSIX shell you could use command substitution to use cat file
as input for echo
:
echo $(cat file1.txt) "This Too"
In Bash you could use process substitution and use echo as another "file" for cat
, as in:
cat file1.txt <(echo This Too)
and then pipe or redirect the output as you see fit.
Like every other answer says, cat ignores stdin if it's got a file to look at. (I do like Daniel & mvw's answers too, +1 for them)
Related videos on Youtube
Ringger81
Updated on September 18, 2022Comments
-
Ringger81 over 1 year
I'd like to concatenate the output from echo with content of a file. I've tried the following comand:
echo "abc" | cat 1.txt > 2.txt
but the
2.txt
file only contains the content from1.txt
. Why doesn't it work?-
Barmar over 6 yearsPrograms like
cat
only read from standard input if they don't have any filename arguments.
-
-
tvdo over 6 yearsThis answer can be improved by explaining how it works and why the OP's original attempt does not work.
-
tvdo over 6 yearsThis answer can be improved by explaining how the suggested alternative works.
-
tvdo over 6 yearsThis answer can be improved by explaining why the OP's original attempt does not work (and therefore why this is necessary instead).
-
Gerard H. Pille over 6 yearsOK, gave it a try.
-
Nubarke over 6 yearsA subshell is not expressly required here, perhaps it would be better to use a group command. See my answer for more details.
-
Gerard H. Pille over 6 yearsAh, but I'd never use bash.
-
G-Man Says 'Reinstate Monica' over 6 yearsThis will (1) put
abc
at the bottom of2.txt
; the question wants it at the top. (2) modify the1.txt
file; this is unacceptable. -
G-Man Says 'Reinstate Monica' over 6 years@GerardH.Pille: While Daniel’s answer quotes from
bash(1)
, it describes behavior that every POSIX-compliant shell must support. -
Nasir Riley over 6 yearsWhere does it say that? Ringger81 never specified where in 2.txt he wanted abc to appear. You are assuming things that the question never states.
-
G-Man Says 'Reinstate Monica' over 6 years(1) OK, you raise a valid point on #1. While the question mentions “output from echo” before “content of a file” in the text, and then puts the
echo
before thecat
in the sample command, I suppose that it never exactly, explicitly, says that it wants the output from echo before the content of the input file. It just seems that most people interpreted it that way. (2)1.txt
is an input file. The question doesn’t say anything about modifying1.txt
. The fact that input files should not be modified goes without saying. -
G-Man Says 'Reinstate Monica' over 6 yearsFor your function to behave properly, you should use
"$1"
and"$2"
. In this context, the curly braces don't do any good. See${name}
doesn’t mean what you think it does …. -
Rhialto supports Monica over 6 yearsThe
<(command)
construction is a bash extension. It is not POSIX, so you can't rely on it in scripts that are supposed to be executed with/bin/sh
. -
Nasir Riley over 6 yearsI can understand your point about not modifying the imput file. My second code will achieve the desired effect without doing so.
-
Chris over 6 years@NasirRiley Your second option is not equivalent to what the OP is looking for, since it will not overwrite
2.txt
if it already exists. It should beecho abc > 2.txt && cat 1.txt >> 2.txt
. -
Nasir Riley over 6 yearsOnce again, it is important to read what the question is. It was never stated as to whether or not Ringger81 wanted to overwrite the contents of the file nor was it ever stated whether or not there was data in the file. You are assuming that such a thing is desired but there is no way for anyone to be clear on that. If he doesn't want the data in 2.txt to be overwritten then your answer would be incorrect. Ringger81 has already shown knowledge of appending data to files so the code can be modified for whichever result is desired.
-
Charles Duffy over 6 yearsHow is the
noclobber
suggestion responsive to the question at hand? (I'm also very much unconvinced that it's good advice -- modifying global behavior tends to break scripts/advice/practices built with defaults in mind). -
Charles Duffy over 6 yearsOpening a file, appending to it, closing it, opening it again, appending to it again... why do that rather than just open it once and keep the redirection in place for both operations?
-
Nasir Riley over 6 yearsWhat does it matter? It's a very simple operation. You're making it seem as though it's something very taxing when it isn't.