Hi I want to prepend text to a file. For example I want to add tasks to the beginning of a todo.txt file. I am aware of echo 'task goes here' >> todo.txt but that adds the line to the end of the file (not what I want).
- 4,931
11 Answers
Linux :
echo 'task goes here' | cat - todo.txt > temp && mv temp todo.txt
or
sed -i '1s/^/task goes here\n/' todo.txt
or
sed -i '1itask goes here' todo.txt
Mac os x :
sed -i '.bak' '1s/^/task goes here\'$'\n/g' todo.txt
or
echo -e "task goes here\n$(cat todo.txt)" > todo.txt
or
echo 'task goes here' | cat - todo.txt > temp && mv temp todo.txt
- 3
- 2
- 111,445
A simpler option in my opinion is :
echo -e "task goes here\n$(cat todo.txt)" > todo.txt
This works because the command inside of $(...) is executed before todo.txt is overwritten with > todo.txt
While the other answers work fine, I find this much easier to remember because I use echo and cat every day.
EDIT: This solution is a very bad idea if there are any backslashes in todo.txt, because thanks to the -e flag echo will interpret them. Another, far easier way to get newlines into the preface string is...
echo "task goes here
$(cat todo.txt)" > todo.txt
...simply to use newlines. Sure, it isn't a one-liner anymore, but realistically it wasn't a one-liner before, either. If you're doing this inside a script, and are worried about indenting (e.g. you're executing this inside a function) there are a few workarounds to make this still fit nicely, including but not limited to:
echo 'task goes here'$'\n'"$(cat todo.txt)" > todo.txt
Also, if you care about whether a newline gets added to the end of todo.txt, don't use these. Well, except the second-to-last one. That doesn't mess with the end.
- 128
- 2
- 19
- 1,261
The moreutils have a nice tool called sponge:
echo "task goes here" | cat - todo.txt | sponge todo.txt
It'll "soak up" STDIN and then write to the file, which means you don't have to worry about temporary files and moving them around.
You can get moreutils with many Linux distros, through apt-get install moreutils, or on OS X using Homebrew, with brew install moreutils.
- 235,242
You can use the POSIX tool ex:
ex a.txt <<eof
1 insert
Sunday
.
xit
eof
https://pubs.opengroup.org/onlinepubs/9699919799/utilities/ex.html
- 1
You can create a new, temporary file.
echo "new task" > new_todo.txt
cat todo.txt >> new_todo.txt
rm todo.txt
mv new_todo.txt todo.txt
You might also use sed or awk. But basically the same thing happens.
- 8,293
If the text file is small enough to fit in memory, you don't have to create a temporary file to replace it with. You can load it all into memory and write it back out to the file.
echo "$(echo 'task goes here' | cat - todo.txt)" > todo.txt
It's impossible to add lines to the beginning of the file without over writing the whole file.
- 802
You cannot insert content at the beginning of a file. The only thing you can do is either replace existing content or append bytes after the current end of file.
Any solution to your question then requires a temporary file (or buffer) to be created (on memory or on disk) which will eventually overwrite the original file.
Beware of not losing data by preserving the original file while creating the new one, should the file system happen to be full during the process. eg:
cat <(echo task go there) todo.txt > todo.txt.new && mv todo.txt.new todo.txt
Final answer
cat <<< "prepended text
$(cat test.txt)" > test.txt
Context
I wasn't too satisfied with the answers as they felt like too much typing. I liked John Alberts his answer but couldn't stand to type -e. Unfortunately, I accidentally read over John Alberts his echo 2 liner as well (significantly reducing the value of this answer and me 30 minutes playing around, but oh well, it happens).
In any case, I was focused on finding something that meant you only needed to type the filename and text you want to prepend.
Moreover, I was searching for something that looked aesthetically intuitive. With that I mean: the preprend needs to physically show, even if it'd be an illusion it'd have the effect of a mnemonic.
So I tried an approach with herestrings since in the right context they reduce cognitive strain (i.e. typing < 3 times doesn't require too much thinking power).
I created a file test.txt with the word "monkeys".
And I typed:
cat <<< "prepend
> $(< test.txt)"
Output:
prepend
monkeys
A bit of clarification:
You need to manually press enter yourself.
On the second line the > is from the shell itself, you don't need to type that.
Notes:
(1) What I couldn't manage was a one liner. There seems to be no herestring combination in which I could use $() and \n. Which is why you need to press the newline manually yourself.
(2) $(< test.txt) has the same effect as $(cat test.txt). The Bash Reference Manual states:
The command substitution
$(cat file)can be replaced by the equivalent but faster$(< file).
So you could also do:
cat <<< "prepend
> $(cat test.txt)"
More typing, but I admit a bit less cognitive strain since cat is being typed twice and is more well-known than the trick of the Bash Reference Manual.
- 191
GitBash + Windows10 + Multline:
Here is a version that lets you use multi-line strings.
##############################################
## This section for demo purpose only, ##
## So you can save entire file as ##
## whatever.sh and run it. ##
## ##
##############################################
> MY_TARGET_FILE.txt ##Make Or Clear File
echo "[STARTER_CONTENT]" >> MY_TARGET_FILE.txt
##############################################
## Below is main code:
##################################################
TARGET_FILE_VARIABLE="MY_TARGET_FILE.txt"
ADD_TO_HEAD_VARIABLE=$(cat << "HEREDOC_HEAD_TEXT"
//| +-------------------------------------+ |//
//| | | |//
//| | MESSAGE_FOR_HEAD_OF_FILE | |//
//| | | |//
//| +-------------------------------------+ |//
HEREDOC_HEAD_TEXT
)
##################################################
TAR=$TARGET_FILE_VARIABLE ##
TEX=$ADD_TO_HEAD_VARIABLE ##
echo "$TEX" | cat - $TAR > TEMP && mv TEMP $TAR ##
##################################################
## Expected contents of MY_TARGET_FILE.txt :
## //| +-------------------------------------+ |//
## //| | | |//
## //| | MESSAGE_FOR_HEAD_OF_FILE | |//
## //| | | |//
## //| +-------------------------------------+ |//
## [STARTER_CONTENT]
- 367
Maybe this, in two commands, is easier to understand. Say that we want to prepend to hello.c from hello.h.
$ cat hello.c >> hello.h
$ mv hello.h hello.c
Before:
% cat hello.c
int main() {
printf("Hello, World!");
return 0;
}
% cat hello.h
#include <stdio.h
After:
% cat hello.c
#include <stdio.h>
int main() {
printf("Hello, World!");
return 0;
}
- 1,118