Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems. 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'd like to be able to run multiple commands on the same file in a single line. The way I currently do this is:

commandA file && commandB file && perl -ne '...' file

My gut instinct tells me that there should be a way to provide the filename argument only once and pipe it to both commands simultaneously through xargs or something similar:

find file | xargs commandA && xargs commandB && xargs perl -ne '...'

When I try this, only the first command runs. How can I achieve what I want to do?

share|improve this question
up vote 12 down vote accepted

You can define a local variable for this:

f=file; commandA $f && commandB $f && ...

You can also execute all unconditionally (replacing && with ;) or in parallel (replacing && with &).

Alternatively, you can also use shell history expansion to reference previous arguments:

commandA file && commandB !:1 && ...
share|improve this answer
    
Not quite what I had in mind, but is an interesting alternative. – Zaid Aug 30 '10 at 9:50
    
What is wrong with this answer? – Chris Aug 30 '10 at 17:48
1  
+1 for keeping it simple. – Stefan Lasiewski Aug 30 '10 at 22:59
    
This is really cool! Is there a way not defining a new variable? – user Feb 4 at 3:20
    
@user, I've added an alternative. – maxschlepzig Feb 4 at 7:39

For shells such as Bash, Korn and Z that have process substitution, you can do this:

find file | tee >(xargs commandA) >(xargs commandB) >(xargs perl -ne '...')
share|improve this answer

I wouldn't vote for this myself. It's silly and dangerous, but just in the interest of listing the ways to do this, there's:

for cmd in "commandA" "commandB" "perl -ne '...'" ; do eval $cmd file ; done

share|improve this answer

You can use xargs to construct a command line e.g.:

echo file | xargs -i -- echo ls -l {}\; wc -l {}

Just pipe the above into bash to run it:

echo file | xargs -i -- echo ls -l {}\; wc -l {} | bash

Extending the example to all the *.c files in the current directory (escaping the ls here to prevent any shell alias substitution):

\ls -1 *.c | xargs -i -- echo ls -l {}\; wc -l {} | bash
share|improve this answer
    
Used this to get a listing of all of files contained in directories where the name is like "enums": find . -name "*enums*" | xargs -i echo -e echo {}\; ls -lh {}\; echo -e '\n\n' | bash – Matt Lachman Jun 2 '11 at 18:34

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.