Take the 2-minute tour ×
Server Fault is a question and answer site for professional system and network administrators. It's 100% free, no registration required.

I need to add this line to every .htaccess file that is located in a /home/*/site/assets/.htaccess where * can be any amount of directories deep

I need to fine this text

RewriteRule ^(.*)$ /site/assets/sym/$1 [L,NS]

and add a line above it, or replace it with this

RewriteCond %{REQUEST_URI} !^/site/assets/sym
RewriteRule ^(.*)$ /site/assets/sym/$1 [L,NS]

I've looked online at this site but I am unclear how to deal with

  1. generating a list of the files I want to edit (so find all files that match this path: /home/*/site/assets/.htaccess)
  2. Adding line breaks in the replace text

Can anyone suggest a resource that will clearly explain it, or fail that, let me know if I am looking at the correct tools for this job?

My OS is Cent OS 5.5, i'm running a LAMP server if that makes much difference, apache 2.

Thanks

share|improve this question
    
This is not a site to give programming advice. So just the hint: Perl can do it! And there is more than one solution for that. –  mailq Oct 16 '11 at 23:23
1  
true, but this is a typical sysadmin task, though? I wouldn't flag this for moving, but that may just be me. –  Kvisle Oct 16 '11 at 23:50

2 Answers 2

You've chosen an excellent set of tools for the job!

Generating a list of files you want to edit is very simple - I'm here assuming you're using a shell which will expand the output of matching filenames, such as bash, or dash:

echo /home/*/site/assets/.htaccess > list.txt

However, if * can mean more than 1 level of directories, I would go with this:

find -name '.htaccess' /home | grep '/site/assets/sym' > list.txt

Your shell will expand the expression into a list, and redirect the output to list.txt. One file for each line.

You can also search for files named .htaccess with find - to see if there's anyone that you've missed, like this:

find -name '.htaccess' /home

Adding line breaks in replace text - this depends a bit on your editor. Line breaks are usually represented as \n

What you want to do, can probably be achieved with a small shell-script - when for variable in expression; do .... done is used, it will execute the lines in between do/done once for each word in expression. NOTE: This can backfire if the paths contain spaces.

for file in /home/*/site/assets/.htaccess; do
    sed 's/RewriteRule \^(.\*)\$ \/site\/assets\/sym\/\$1 \[L,NS\]/RewriteCond %{REQUEST_URI} !^\/site\/assets\/sym\nRewriteRule \^(.\*)\$ \/site\/assets\/sym\/\$1 \[L,NS\]/g' $file > $file.new
    mv $file $file.old
    mv $file.new $file
done

(This will leave a file named .htaccess.old in its spot.)

Rewritten for alternate list-gathering-approach:

for file in $(find -name '.htaccess' /home | grep '/site/assets/sym'); do
    sed 's/RewriteRule \^(.\*)\$ \/site\/assets\/sym\/\$1 \[L,NS\]/RewriteCond %{REQUEST_URI} !^\/site\/assets\/sym\nRewriteRule \^(.\*)\$ \/site\/assets\/sym\/\$1 \[L,NS\]/g' $file > $file.new
    mv $file $file.old
    mv $file.new $file
done

Or, in one line, without taking a backup:

for file in /home/*/site/assets/.htaccess; do sed -i 's/RewriteRule \^(.\*)\$ \/site\/assets\/sym\/\$1 \[L,NS\]/RewriteCond %{REQUEST_URI} !^\/site\/assets\/sym\nRewriteRule \^(.\*)\$ \/site\/assets\/sym\/\$1 \[L,NS\]/g' $file; done
share|improve this answer
    
+1 for effort so far, this is definitely leading me in the right direction. This post has brought up some other concerns I have just thought about. Will the shell script only create a .old file if the searched line exists? or will it recreate all .htaccess files regardless of whether they have that line in it or not... –  Jason Oct 17 '11 at 1:12
    
Also, the echo command didn't quite work, cat list.txt /home/*/site/assets/.htaccess –  Jason Oct 17 '11 at 1:13
    
I suspect the echo command didn't work because you have several levels of directories. I should also note that you need to use bash. To answer the ".old"-file question; yes - it will only do it if the file exists. It executes the three lines once for each found file. –  Kvisle Oct 17 '11 at 5:37

You can use sed to insert the line above the matched pattern and make backups as you go.

for file in  $( find /home -name .htaccess | grep /site/assets/sym); do
    sed -i.bak '/RewriteRule \^(.\*)\$ \/site\/assets\/sym\/\$1 \[L,NS\]/i RewriteCond %{REQUEST_URI} !^/site/assets/sym' "$file"
done
  • sed -i.bak will edit the files in place and create a .bak file for each one
  • /PATTERN/i another pattern - match PATTERN and insert another pattern before it.
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.