Super User is a question and answer site for computer enthusiasts and power users. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I have a directory tree of files I need to loop through and reformat the lines. can I do this with sed with some combination of find?

for each file, I'll need to adjust the text in the file from

* @category Foo
* @package Bar

into just this (Remove the @category line, but prepend the value to the package annotation value)

* @package Foo/Bar

what is the most efficient way of doing this? its a few hundred files that will be modified.

share|improve this question
I don't know how to use sed, but if you are able to write a bash script, which does this operation for one file, you can do it for every file in the directory tree by using "find ./ -exec bash-script {} \;" – FSMaxB Dec 19 '12 at 20:53

Try this:

sed '/@category/{s/.*@category /* @package /;N;s/\n.*@package /\//}'

To run this against all the files in a whole tree, I would do something like this:

for i in $(find . -type f); do
   sed '/@category/{s/.*@category /* @package /;N;s/\n.*@package /\//}' $i > $
   mv $ $i
share|improve this answer
Nice work. But since he's using Linux (GNU sed), why wouldn't you use sed -i to replace inline, and do away with the loop using find -type f -exec sed -i ... {} + ? – tink Dec 19 '12 at 21:27
Sure, you can do that. Largely a matter of taste. But that is a non-standard extension and that bit of knowledge about sed is less generally useful than knowing how to use a for loop. Also, explicitly looping also gives you the chance, if you want, to modify the behavior to preview what will happen (by removing the mv statement) or undo it (if you add a mv $i $i.old). – Nicole Hamilton Dec 19 '12 at 21:41

This might work for you (GNU sed):

find . -type f -exec sed -ri '$!N;s/^\* @category (.*)\n(\* @package )(.*)/\2\1\/\3/;P;D' {} \;
share|improve this answer

When you have to work on multiple lines, comes in mind, it's more suitable than sed to do this.

awk '/^\* +@package/{print $0"/"v;next} {if ($0 ~ /^\* +@category/){v=$3}else{print}}' file.txt

Or decomposed :

awk '
    /^\* +@package/{
        print $0"/"v
        if ($0 ~ /^\* +@category/){
' file.txt
share|improve this answer
One True awk :) – user151547 Dec 19 '12 at 21:23

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .