6

This should be an absurdly easy task: I want to take each line of the stdout of any old command, and use each to execute another command with it as an argument.

For example:

ls | grep foo | applycommand 'mv %s bar/'

Where this would take everything matching "foo" and move it to the bar/ directory.

(I feel a bit embarrassed asking for what is probably a ridiculously obvious solution.)

jameshfisher
  • 29,645
  • 26
  • 105
  • 155

3 Answers3

16

That program is called xargs.

ls | grep foo | xargs -I %s mv %s bar/
Chris Jester-Young
  • 213,251
  • 44
  • 377
  • 423
  • 4
    xargs also lets you insert arguments in the middle of the command by specifying a substitution string. i.e. `xargs -I FILE mv FILE bar/` – Martin Mar 04 '10 at 01:28
  • @Martin: Thanks, I learnt something new! Will update my answer accordingly. – Chris Jester-Young Mar 04 '10 at 01:38
  • 1
    also mv has a --target option. so just: | xargs mv --target=bar/ – pixelbeat Mar 04 '10 at 10:33
  • @pixelbeat: Thanks! I was trying to model my answer after what the OP wanted (with `%s` and all), but obviously in this case, your solution is even better. – Chris Jester-Young Mar 04 '10 at 17:23
  • this doesn't execute a command for each line of stdin. It just bundles it together in one shot. The OP mentions this case only as an example. :\ – Karthick Dec 07 '13 at 01:50
  • @Karthick Correct, the question title is an [XY problem](http://meta.stackexchange.com/q/66377/13), so I solved the _real_ problem with my answer. – Chris Jester-Young Dec 07 '13 at 02:10
7
ls | grep foo | while read FILE; do mv "$FILE" bar/; done

This particular operation could be done more simply, though:

mv *foo* bar/

Or for a recursive solution:

find -name '*foo*' -exec mv {} bar/ \;

In the find command {} will be replaced by the list of files that match.

John Kugelman
  • 330,190
  • 66
  • 504
  • 555
  • Almost right: when doing `-exec ... +`, the `{}` must immediately precede the `+`. You can use the `;` form though: `-exec mv {} bar/ ';'`. – Chris Jester-Young Mar 04 '10 at 01:25
0

for your case, do it simply like this.

for file in *foo*
do
   if [ -f "$file" ];then
      mv "$file" /destination
   fi
done

OR just mv it if you don't care about directories or files

mv *foo* /destination
ghostdog74
  • 307,646
  • 55
  • 250
  • 337