Reputation: 43
I have
/var/log/syslog
{
rotate 7
daily
missingok
notifempty
delaycompress
compress
postrotate
invoke-rc.d rsyslog rotate > /dev/null
endscript
}
/var/log/mail.info
/var/log/mail.warn
/var/log/mail.err
/var/log/mail.log
/var/log/daemon.log
/var/log/kern.log
/var/log/auth.log
/var/log/user.log
/var/log/lpr.log
/var/log/cron.log
/var/log/debug
/var/log/messages
{
rotate 4
weekly
missingok
notifempty
compress
delaycompress
sharedscripts
postrotate
invoke-rc.d rsyslog rotate > /dev/null
endscript
}
What I want to do is insert olddir /var/log/oldlog
a line before the top rotate 7
and lower rotate 4
lines.
Is it possible to make sed
do possible multiple insertions?
Also it also needs to ignore the rotate >
pattern in the postrotate.
I thought I would ask before I try and do something longwinded and horrid. Also the above is the main question but a secondary one would be to iterate all files in the directory with the above.
Any pointers would be really appreciated
Upvotes: 1
Views: 285
Reputation: 12438
Input:
$ cat input_file
/var/log/syslog
{
rotate 7
daily
missingok
notifempty
delaycompress
compress
postrotate
invoke-rc.d rsyslog rotate > /dev/null
endscript
}
/var/log/mail.info
/var/log/mail.warn
/var/log/mail.err
/var/log/mail.log
/var/log/daemon.log
/var/log/kern.log
/var/log/auth.log
/var/log/user.log
/var/log/lpr.log
/var/log/cron.log
/var/log/debug
/var/log/messages
{
rotate 4
weekly
missingok
notifempty
compress
delaycompress
sharedscripts
postrotate
invoke-rc.d rsyslog rotate > /dev/null
endscript
}
Command:
sed -i.bak '/rotate [0-9]\+/{s@^\( \+\)@\1olddir /var/log/oldlog\n\1@}' input_file
Output:
$ cat input_file
/var/log/syslog
{
olddir /var/log/oldlog
rotate 7
daily
missingok
notifempty
delaycompress
compress
postrotate
invoke-rc.d rsyslog rotate > /dev/null
endscript
}
/var/log/mail.info
/var/log/mail.warn
/var/log/mail.err
/var/log/mail.log
/var/log/daemon.log
/var/log/kern.log
/var/log/auth.log
/var/log/user.log
/var/log/lpr.log
/var/log/cron.log
/var/log/debug
/var/log/messages
{
olddir /var/log/oldlog
rotate 4
weekly
missingok
notifempty
compress
delaycompress
sharedscripts
postrotate
invoke-rc.d rsyslog rotate > /dev/null
endscript
}
Explanations:
-i.bak
will activate the option to take a backup of each file before modifying them and add the suffix .bak
at the end of each filename./rotate [0-9]\+/
will only take the lines that contain rotate
followed by a space and an integersed
encounters one of those lines, it will execute s@^\( \+\)@\1olddir /var/log/oldlog\n\1@
which is a find and replace command that will replace the beginning of the line as well as all the spaces by the pattern. I have taken into account the spaces to keep the indentation by using back reference \1
.2nd question:
find /path/to/my/files -type f -exec sed -i.bak '/rotate [0-9]\+/{s@^\( \+\)@\1olddir /var/log/oldlog\n\1@}' {} \;
You might add -name 'YOUR FILE PATTERN'
if you want to reduce the find scope. Also consider using -maxdepth N
to limit the depth in term of subdirs of the search
Update:
As the text contains a mix of \t
and spaces, we can use the following POSIX class [:blank:]
that will match those 2 characters.
Command:
sed -i.bak '/^[[:blank:]]*rotate[[:blank:]]\+[0-9]\+[[:blank:]]*$/{s@^\([[:blank:]]*\)@\1olddir /var/log/oldlog\n\1@}' input_file
Upvotes: 3