1

How do I pipe commands and their results in Ubuntu when writing them in the terminal. I would write the following commands in sequence -

$ ls | grep ab
abc.pdf
cde.pdf
$ cp abc.pdf cde.pdf files/

I would like to pipe the results of the first command into the second command, and write them all in the same line. How do I do that ?

something like

$ cp "ls | grep ab" files/

(the above is a contrived example and can be written as cp *.pdf files/)

1
  • cp `ls | grep ab` files/ -- notice the surrounding backticks Commented Jul 21, 2012 at 17:48

3 Answers 3

6

Use the following:

cp `ls | grep ab` files/
Sign up to request clarification or add additional context in comments.

1 Comment

Good solution, as long as the number of matching files is decently controlled. The maximum size of a command line is pretty large now-a-days, but isn't infinite. Still, for most practical uses it is just fine.
6

Well, since the xargs person gave up, I'll offer my xargs solution:

ls | grep ab | xargs echo | while read f; do cp $f files/; done

Of course, this solution suffers from an obvious flaw: files with spaces in them will cause chaos.

An xargs solution without this flaw? Hmm...

ls | grep ab | xargs '-d\n' bash -c 'docp() { cp "$@" files/; }; docp "$@"'

Seems a bit klunky, but it works. Unless you have files with returns in them I mean. However, anyone who does that deserves what they get. Even that is solvable:

find . -mindepth 1 -maxdepth 1 -name '*ab*' -print0 | xargs -0 bash -c 'docp() { cp "$@" files/; }; docp "$@"'

7 Comments

xargs echo is ... interesting. It may as well be omitted from the pipeline.
@WilliamPursell: Not at all. It forces multiple arguments to be on the same input line. Compare: ls | xargs echo | wc -l vs ls | wc -l. Assuming you have multiple files in your directory of course.
The xargs does force more output onto a single line, so that fewer instances of cp are executed, but it does not change the result.
@WilliamPursell: Of course. That's the whole point. Added efficiency without drawbacks is nothing to be sneezed at.
There is a drawback. With xargs, nothing is done until ls outputs enough names that xargs is able to collect enough arguments to force an instance of cp to be executed. That's a waste of time and memory, with no benefit. The actions here are not CPU bound, and the time to spawn cp is (probably) insignificant compared to the execution of each cp.
|
4

To use xargs, you need to ensure that the filename arguments are the last arguments passed to the cp command. You can accomplish this with the -t option to cp to specify the target directory:

ls | grep ab | xargs cp -t files/

Of course, even though this is a contrived example, you should not parse the output of ls.

3 Comments

Except of course this doesn't handle files with spaces (easy to fix) or control characters (easy to fix) or returns (hard to fix) in it. However, I didn't know about -t so you get the upvote.
Right, depending what actually comes in the pipeline before xargs. Using GNU tools, find ... -print0 | xargs -0 can take care of filenames with whitespace
Exactly so, but your solution didn't offer this. My suggestion of using xargs, three hours before yours, did.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.