问题
Is there a Unix command to prepend some string data to a text file?
Something like:
prepend \"to be prepended\" text.txt
回答1:
sed -i.old '1s;^;to be prepended;' inFile
-i
writes 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.
回答2:
printf '%s\n%s\n' "to be prepended" "$(cat text.txt)" >text.txt
回答3:
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 (zsh only)
Using a here-string - <<<
, you can do:
<<< "to be prepended" < text.txt | sponge text.txt
回答4:
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
回答5:
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
回答6:
Prefer Adam's answer
We can make it easier to use sponge. Now we don't need to create a temporary file and rename it by
echo -e "to be prepended \n another line" | cat - text.txt | sponge text.txt
回答7:
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...
回答8:
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
-s
suppresseded
's status messages.- Note how the commands are provided to
ed
as a multi-line here-document (<<'EOF' ... EOF
), i.e., via stdin. 1i
makes1
(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. w
writes the result back to the input file (for testing, replacew
with,p
to only print the result, without modifying the input file).
回答9:
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
.
回答10:
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
回答11:
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
回答12:
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.
回答13:
Another fairly straight forward solution is:
$ echo -e "string\n" $(cat file)
回答14:
If you like vi/vim, this may be more your style.
printf '0i\n%s\n.\nwq\n' prepend-text | ed file
回答15:
# 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
回答16:
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