Tell me more ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

So, I have a bunch of files in a directory, and I need to insert a line of text into each of them. They have essentially the following format:


<VirtualHost *:80>
        ServerAdmin gabe@localhost
        DocumentRoot /var/www/test1
        ServerName test1.local
        ServerAlias test1
        <Directory "/var/www/test1">
                Options All
                AllowOverride All
        </Directory>
</VirtualHost>

And I'd like to insert a line before the closing

</VirtualHost>
tag. My first assumption is that I should be able to do this with sed, probably matching and replacing that tag. I'm going to start attempting this now, but if anyone has a existing way to do this, I'd love to hear it.

share|improve this question
I'll be honest when I say I think this is more of a programming task... and thus should be on SO. I'd use Perl to do it, esp since I bet there's a perl module designed to parse, and modify apache configs. – xenoterracide Aug 24 '10 at 19:22
2  
Thanks, but it's a task that should be easy to accomplish with simple unix tools, hence asked here. Thanks for your comment, though. – gabe. Aug 24 '10 at 19:30

3 Answers

up vote 8 down vote accepted

Something like this:

sed 's/<\/VirtualHost>/yourlinehere\n<\/VirtualHost>/'

works. If you want to repeat this command on a lot of file you can do something like:

for i in *; do sed -i 's/<\/VirtualHost>/yourlinehere\n<\/VirtualHost>/' "$i"; done

Probably better (but untested) thanks to @ChrisDown:

find . -type f -print0 | while IFS= read -r -d '' filename;\
do sed -i 's/<\/VirtualHost>/yourlinehere\n<\/VirtualHost>/' $filename;\ 
done
share|improve this answer
awesome... this is just what I was looking for. – gabe. Aug 24 '10 at 19:29
Do not parse ls. Use a glob instead. mywiki.wooledge.org/ParsingLs – Chris Down Nov 14 '11 at 15:36
You are rigth @ChrisDown. Please, improve my answer. – lcipriani Nov 23 '11 at 14:14
@lcipriani Er, if you insist, but you should be able to do it yourself too. – Chris Down Nov 23 '11 at 16:26

If you don't mind Perl try:

perl -pi'*.old' -e 's(</VirtualHost>(Your stuff here\n</VirtualHost>)' myfile

The -i switch will save your old file with a .old extension and print to the current one.

share|improve this answer

You can also use "ex" (command-line vi) if the editing you want to do is even somewhat complicated. For example, you only want to do the insert for on one instance of "".

A shell script like this can work:

for FILENAME in *.whatever  # Need a criteria to glob, or a list of names
do
    ex -s $FILENAME << END_EDITS
/^<\/VirtualHost>/
O " capital-o, not zero
text to insert goes here
.
w!
q
END_EDITS
done

This approach gives you the advantages of "ex": finding a location with elaboarte patterns, and 'cursor movements'. You can do things like find a pattern, then find the next instance, THEN do the insert. Or you can change text, rather than just doing inserts. Or you can change between ranges. Don't forget that "ex" lets you use "." as the current line, so .,/^somepatter/s/blah/foo/ will work.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.