Take the 2-minute tour ×
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.

Sometimes commands repeat in pipeline command. For example (just to illustrate):

$ grep -lF 'pattern' ./foo/**/*.bar | xargs dirname | xargs dirname

Is there a way to shorten chaining command? For example, I have a command:

$ ... | some-command | some-command | some-command | ...

I'd like to get same result with something like to the following

$ ... | (some-command) ^ 3 | ...

Of course, it wouldn't work, but it illustrates what I'd like to make.

share|improve this question
2  
There is no way to do that –  Alex Layton Feb 4 at 16:54
    
@AlexLayton I beg to differ. –  kojiro Feb 5 at 3:53

2 Answers 2

Recursion + evil:

repiper() { 
    local -i n="$1";
    shift;
    if (( n )); then
        eval "$@" | repiper $((n-1)) "$@";
    else
        eval "$@";
    fi
}

$ grep -lRF function dev/jquery/build | repiper 3 xargs -n1 dirname | head
.
.
dev
dev
dev
dev
$ grep -lRF function dev/jquery/build | repiper 1 xargs -n1 dirname | head
dev/jquery
dev/jquery
dev/jquery/build
dev/jquery/build
dev/jquery/build
dev/jquery/build
$ grep -lRF function dev/jquery/build | repiper 0 xargs -n1 dirname | head
dev/jquery/build
dev/jquery/build
dev/jquery/build/tasks
dev/jquery/build/tasks
dev/jquery/build/tasks
dev/jquery/build/tasks
share|improve this answer
    
+1; Nice bash macro –  Clayton Stanley Feb 5 at 6:29

Not beautiful but I believe you can do what you want using a while and a for loop.

$ seq 5 | while read -r f; do for i in {1..3}; do echo "[$i]: blah $f";done; done
[1]: blah 1
[2]: blah 1
[3]: blah 1
[1]: blah 2
[2]: blah 2
[3]: blah 2
[1]: blah 3
[2]: blah 3
[3]: blah 3
[1]: blah 4
[2]: blah 4
[3]: blah 4
[1]: blah 5
[2]: blah 5
[3]: blah 5

Here's the construct broken out:

$ <CMD> | while read -r f; do 
    for i in <range>; do 
        ...do command some num. of times...
    done 
done

Other approaches

  1. The other way to view this would be to create a shell function (function () {...}) and call that instead of xargs ... multiple times. This function coud take 2 arguments, a number of times to run argument, and an argument to run.

  2. You could also create a shell script that would contain a for loop that you could pass into it 2 arguments. The number of times to run X, and the argument to operate on X.

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.