$ echo {a,b,c}.h d e.h |xargs -IA find A -name '*.h'
find: `a.h b.h c.h d e.h': No such file or directory
$ echo -e a.h\\nb.h c.h d e.h |xargs -IA find A -name '*.h'
find: `b.h c.h d e.h': No such file or directory

The problem is that -I implies xargs will assume arguments are delimited by newline. I'm not sure why that is. I reckon I can solve this problem with sed, but I wonder if there's an xargs trick or idiom I'm not familiar with that people use to solve this.

I'm looking for a solution that will also work on OS X. On OS X the xargs -J switch seems to work fine. The manpage claims this switch will just control where the arguments are placed for the executable -- which is exactly what I want.


Hmm. Do you need the pipe and xargs? It seems like all your example really needs is the find and the echo.

I'm guessing this is a piece of a larger puzzle, so this may not work in the context of what you're doing, but your example could be written as:

$ find `echo {a,b,c}.h d e.h` -name '*.h'

$ find $(echo {a,b,c}.h d e.h) -name '*.h'

... which, on my system, results in find checking each argument individually:

find: `a.h': No such file or directory
find: `b.h': No such file or directory
find: `c.h': No such file or directory
find: `d': No such file or directory
find: `e.h': No such file or directory

I don't have an OSX machine to test with, and these may be bash-specific.

  • My original intent was to have the list of directories and files coming from stdin. I'll have to do with one of the workarounds. I'm still curious why -I implies delimiting by newline though. – wilhelmtell Feb 7 '10 at 20:40
  • give it time, someone else might have a real answer for you. i thought maybe you needed the expansion, not the stdin. – quack quixote Feb 7 '10 at 20:50

Why not just find {a,b,c}.h d e.h -name '*.h'?

  • see his comment on my answer; he needs the argument list coming from stdin. (good simplification of my answer, at least in the example find+echo case.) – quack quixote Feb 7 '10 at 21:28
  • Ok, if you need the list coming from stdin, then you must try to do one of the following: 1. Don't use spaces in directory names, and then pipe things through sed -e 's/\s+/\n/g'; 2. Find a way to separate the incoming directory names by newlines or nulls, and then use either xargs --null find ... or while read x; do ... ; done. – Ryan Thompson Feb 9 '10 at 16:58

did you try the -d option to xargs?

justin@eee:~$ echo {a,b,c}.h d e.h |xargs -d ' ' -n1  -IA echo foo A
foo a.h
foo b.h
foo c.h
foo d
foo e.h

or even simpler,

justin@eee:~$ for x in $(echo {a,b,c}.h d e.h);do echo foo $x;done
foo a.h
foo b.h
foo c.h
foo d
foo e.h
  • -I implies ignoring -d. Besides, -d takes exactly one character as argument. You can't have arbitrary whitespace as delimiter. That is, in terms of regex it's / / but you can't do /\s/ or even /\s+/. – wilhelmtell Feb 8 '10 at 1:42
  • works fine for me, see my comment. If this still isn't what you want, you are going to have to give a better example that shows what you are really trying to do. – user23307 Feb 8 '10 at 5:14

Use GNU Parallel:

parallel -q find {} -name '*.h' ::: {a,b,c}.h d e.h

Watch the intro video to learn more: http://www.youtube.com/watch?v=OpaiGYxkSuQ

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.