views:

1039

answers:

4

I would like to prepend some text to multiple files in bash, I've found this post that deals with prepend: prepend to a file one liner shell?

And I can find all the files I need to process using find:

find ./ -name "somename.txt"

But how do I combine the two using a pipe?

A: 
find . -name "somename.txt" | while read a; do prepend_stuff_to "$a" ; done

or

find . -name "somename.txt -exec prepend_stuff_to "{}" \;
mitchnull
+1  A: 
find . -name "somefiles-*-.txt" -type f | while read line; do  sed -i 'iThis text gets prepended' -- "$line"; done

or

find . -name "somefiles-*-.txt" -type f | xargs sed -i 'iGets prepended' --

The best (I think):

find . -name "somefiles-*-.txt" -type f -exec sed -i 'iText that gets prepended (dont remove the i)' -- '{}' \;

Thanks for the missing "-hint. I added the important --s then, too.

Johannes Weiß
it's usually better to quote $line ("$line"). Unfortunately filenames with spaces in them are common nowadays...
mitchnull
yep, thats true!
Johannes Weiß
This may be a GNU-ism; original sed wants 'i\ followed by a newline, followed by text to be appended.
Charlie Martin
For #2, you want to use -print0 with find and -0 with xargs to avoid having problems with folders with spaces in their names. For #3, you should use \+ instead of \; to avoid forking a process for each file.
Adam Rosenfield
A: 
find ./ -name "somename.txt" -print0 | xargs -0 -n 1 prepend_stuff_to
Paul Tomblin
+4  A: 

You've got several options. Easiest is probably sed:

find ./ -name somename.txt -exec sed -e '1i
My new text here` {} \;

It'll be faster if you add '2q' to tell it you're done after prepanding the text, and if will happen in place in the file with the -i flag

find ./ -name somename.txt -exec sed -i .bak -e '2q;1i
My new text here` {} \;

That leaves the original files around with a .bak extension.

Charlie Martin
This one seemed to do it for me, the other good examples inserted the text multiple times (one for each new line I think) I just had to add -type file and change the -e to -i to get sed to update the files.
DEfusion
Yup. Using 'iText' matches every line, so inserts the text ahead of each line. '1i' matches only the first line. '0a' would do the same. The '2q' isn't really necessary, but keeps sed from having to look at each line and say 'no, this isn't line 1 either'.
Charlie Martin