Is there a Unix command to prepend some string data to a text file?
Something like:
prepend "to be prepended" text.txt
sed -i.old '1s;^;to be prepended;' inFile
-iwrites the change in place and take a backup if any extension is given. (In this case,.old)1s;^;to be prepended;substitutes the beginning of the first line by the given replacement string, using;as a command delimiter.
printf '%s\n%s\n' "to be prepended" "$(cat text.txt)" >text.txt
Process Substitution
I'm surprised no one mentioned this.
cat <(echo "before") text.txt > newfile.txt
which is arguably more natural than the accepted answer (printing something and piping it into a substitution command is lexicographically counter-intuitive).
...and hijacking what ryan said above, with sponge you don't need a temporary file:
sudo apt-get install moreutils
<<(echo "to be prepended") < text.txt | sponge text.txt
EDIT: Looks like this doesn't work in Bourne Shell /bin/sh
Here String
Using a here-string - <<< (again, you need bash), you can do:
<<< "to be prepended" < text.txt | sponge text.txt
This is one possibility:
(echo "to be prepended"; cat text.txt) > newfile.txt
you'll probably not easily get around an intermediate file.
Alternatives (can be cumbersome with shell escaping):
sed -i '0,/^/s//to be prepended/' text.txt
This will work to form the output. The - means standard input, which is provide via the pipe from echo.
echo -e "to be prepended \n another line" | cat - text.txt
To rewrite the file a temporary file is required as cannot pipe back into the input file.
echo "to be prepended" | cat - text.txt > text.txt.tmp
mv text.txt.tmp text.txt
Probably nothing built-in, but you could write your own pretty easily, like this:
#!/bin/bash
echo -n "$1" > /tmp/tmpfile.$$
cat "$2" >> /tmp/tmpfile.$$
mv /tmp/tmpfile.$$ "$2"
Something like that at least...
In some circumstances prepended text may available only from stdin. Then this combination shall work.
echo "to be prepended" | cat - text.txt | tee text.txt
If you want to omit tee output, then append > /dev/null.
Solution:
printf '%s\n%s' 'text to prepend' "$(cat file.txt)" > file.txt
Note that this is safe on all kind of inputs, because there are no expansions. For example, if you want to prepend !@#$%^&*()ugly text\n\t\n, it will just work:
printf '%s\n%s' '!@#$%^&*()ugly text\n\t\n' "$(cat file.txt)" > file.txt
The last part left for consideration is whitespace removal at end of file during command substitution "$(cat file.txt)". All work-arounds for this are relatively complex. If you want to preserve newlines at end of file.txt, see this: https://stackoverflow.com/a/22607352/1091436
If it's acceptable to replace the input file:
Note: Doing so may have unexpected side effects, notably replacing a symlink with a regular file, possibly ending up with different permissions on the file, and changing the file's creation (birth) date.
sed -i, as in Prince John Wesley's answer, tries to at least restore the original permissions, but the other limitations apply.
{ printf 'line 1\nline 2\n'; cat text.txt; } > tmp.txt && mv tmp.txt text.txt
Note: Using a group command { ...; ... } is more efficient than using a subshell ((...; ...)).
If the input file should be edited in place (preserving its inode with all its attributes):
Using the venerable ed POSIX utility:
Note: ed invariably reads the input file as a whole into memory first.
ed -s text.txt <<'EOF'
1i
line 1
line 2
.
w
EOF
-ssuppresseded's status messages.- Note how the commands are provided to
edas a multi-line here-document (<<'EOF' ... EOF), i.e., via stdin. 1imakes1(the 1st line) the current line and starts insert mode (i).- The following lines are the text to insert before the current line, terminated with
.on its own line. wwrites the result back to the input file (for testing, replacewwith,pto only print the result, without modifying the input file).
Another way using sed:
sed -i.old '1 {i to be prepended
}' inFile
If the line to be prepended is multiline:
sed -i.old '1 {i\
to be prepended\
multiline
}' inFile
As tested in Bash (in Ubuntu), if starting with a test file via;
echo "Original Line" > test_file.txt
you can execute;
echo "$(echo "New Line"; cat test_file.txt)" > test_file.txt
or, if the version of bash is too old for $(), you can use backticks;
echo "`echo "New Line"; cat test_file.txt`" > test_file.txt
and receive the following contents of "test_file.txt";
New Line
Original Line
No intermediary file, just bash/echo.
Another fairly straight forward solution is:
$ echo -e "string\n" $(cat file)
If you like vi/vim, this may be more your style.
printf '0i\n%s\n.\nwq\n' prepend-text | ed file
# create a file with content..
echo foo > /tmp/foo
# prepend a line containing "jim" to the file
sed -i "1s/^/jim\n/" /tmp/foo
# verify the content of the file has the new line prepened to it
cat /tmp/foo
I didn't really like any of the answers here, so I built my own command: pre.
Install with go:
go get -u github.com/Flaque/pre
Prepend some text from stdin to a file with:
echo "some at the start" | pre myFile.txt | sponge myFile.txt
The command doesn't write in place, it just outputs to stdout, so you'll need the sponge from moreutils on the end to save the file.
I'd recommend defining a function and then importing and using that where needed.
prepend_to_file() {
file=$1
text=$2
if ! [[ -f $file ]] then
touch $file
fi
echo "$text" | cat - $file > $file.new
mv -f $file.new $file
}
Then use it like so:
prepend_to_file test.txt "This is first"
prepend_to_file test.txt "This is second"
Your file contents will then be:
This is second
This is first
I'm about to use this approach for implementing a change log updater.
来源:https://stackoverflow.com/questions/10587615/unix-command-to-prepend-text-to-a-file