I have a command find "$PWD" -name __openerp__.py|awk -F/ -vOFS=/ 'NF-=2'|sort -u and I want to take a certain line containing /web/addons and push it to the front of output then do the same with /openerp/addons making so that line with /openerp/addons would be first and line with /web/addons would be second.

I figured to use grep with that input and from the same output - grep with wildcard and exclude, but yet to figure out how to pass pipe output to multiple greps. Also there is probably multiple ways of doing this.

So right now I get:

<my path>/addons
<my path>/development
<my path>/external
<my path>/server/openerp/addons
<my path>/web/addons

And I want it to become:

<my path>/server/openerp/addons
<my path>/web/addons
<my path>/addons
<my path>/development
<my path>/external

P.S. Reversal of sort will not solve this

  • This will not work in a pipeline: it needs to buffer all output lines until it finds the ones you're interested in before outputting anything. – Joseph R. Jan 29 '14 at 14:02
  • actually I'm fine to hold buffer in /tmp/. I'm mainly interested in it being one liner. – JackLeo Jan 29 '14 at 14:09

I'm not sure I understand what you're trying to do here but if all you want is to have the line with /openerp/addons to be first and /web/addons to be second, why not just something like this:

find "$PWD" -name '__openerp__.py' | awk -F/ -vOFS=/ 'NF-=2' | 
  sed 's#^\(.*/openerp/addons.*\)#aaa%\1#; s#^\(.*/web/addons.*\)#aab%\1#' | 
   sort -u | sed 's/^aa.%//'

Not particularly clever or elegant but this will simply add aaa% to the beginning of lines containing /openerp/addons and aab% to the beginning of lines containing /web/addons. The last sed removes them again after sorting. Assuming you have no files whose name starts with aa.%, that should have the desired result.

Or, you could use a simple perl one-liner that also does the job of sort -u:

find fafa/ | awk -F/ -vOFS=/ 'NF-=2' | 
 perl -ne 's#^(.*/openerp/addons)#aaa%$1#; s#^(.*/web/addons)#aab%$1#; $k{$_}++; 
            END{for (sort keys(%k)){s/^aa.%//; print }}'
| improve this answer | |

As I mentioned in a comment, pipelines are not the way to go; at least not with a tool as simple as grep. I would use a more powerful tool, such as Python or Perl, for this. Here's a Perl filter that might help:

your command | perl -ne '
        print # print the current line as is
    } else{
        if   (m{/web/addons}    ) { $web=$_     and $found_web++    }
        elsif(m{/openerp/addons}) { $openerp=$_ and $found_openerp++}
        else                      { push @buffer,$_                 }
        $already_found_lines = ($found_web and $found_openerp);
        if($already_found_lines)  { print "${openerp}$web";print for @buffer}

This tested correctly with your sample input.

| improve this answer | |
  • Thanks, but I do have a code with python, but as mentioned I just wanted it to make bash one liner. So in my case although this is great and works - it's not something I will end up using. – JackLeo Jan 29 '14 at 14:26
  • @JackLeo Technically, this is a one-liner (whatever that may mean) :). It's not Bash, though, and neither is your solution, which simply uses Bash to invoke external tools. – Joseph R. Jan 29 '14 at 14:29
  • Well yes you're right. I give you that. Just for something as simple perl seems to be bit of a overkill. I could just pasted the same python code to '' and that would be a one liner as well. – JackLeo Jan 29 '14 at 14:31
  • @JackLeo I think the "overkillness" of this approach is highly debatable. Would using a simple Python code instead of 4 tool invocations (along with a subshell) be overkill? Also, the higher level code has the advantage of being more readable (in my opinion, at least). – Joseph R. Jan 29 '14 at 14:34
  • yes I do agree with you, but then why even bother with something passing info to perl/python code while it can get the same info itself. – JackLeo Jan 29 '14 at 14:39

Right now I did it by saving to /tmp/ and then executing grep on it few times:

find "$PWD" -name '__openerp__.py' | awk -F/ -vOFS=/ 'NF-=2' | sort -u > /tmp/openerp_addon_list.txt ; (egrep '/openerp/addons|/web/addons$' /tmp/openerp_addon_list.txt; egrep -v "/openerp/addons|/web/addons|/openerp/test" /tmp/openerp_addon_list.txt)
| improve this answer | |
  • Did this work for you? Because on my system it only prints two lines given your sample input: <my path> followed by <my path>/server. – Joseph R. Jan 29 '14 at 14:26
  • yep it works. also I pass output to | tr "\n" "," | sed 's/,$/ /' | tr " " "\n" but this is a bit out of this question boundaries. Maybe my sample is wrong in this case. – JackLeo Jan 29 '14 at 14:28
  • Edited and added output. – JackLeo Jan 29 '14 at 14:32

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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