问题
example use of xargs
application in Unix can be something like this:
ls | xargs echo
which is the same as (let's say I have someFile
and someDir/
in the working directory):
echo someFile someDir
so xargs
take its input and place it at the end of the next command (here at the end of echo).
But sometimes I want xargs
to place its input somewhere in the middle of next command.
For example:
find . -type f -name "*.cpp" -print | xargs g++ -o outputFile
so if I had in the current directory files a.cpp
, b.cpp
, c.cpp
the output would be the same as with the command:
g++ -o outputFile a.cpp b.cpp c.cpp
but I want to have something like this:
g++ a.cpp b.cpp c.cpp -o outputFile
Is there a way to do it?
P.S.: I need it in some cases, because e.g.:
i586-mingw32msvc-g++ -o outputFile `pkg-config --cflags --libs gtkmm-2.4` a.cpp b.cpp c.cpp
doesn't work but this one works fine:
i586-mingw32msvc-g++ a.cpp b.cpp c.cpp -o outputFile `pkg-config --cflags --libs gtkmm-2.4`
回答1:
To answer the original question asked in the title of how to use xargs
with the input in the middle rather than the end:
$ echo a b c | xargs -I {} echo before {} after
before a b c after
This replaces {}
in the command with the piped output. There are some subtle differences between BSD and GNU xargs described below:
BSD xargs (e.g. on MacOS/Darwin, freebsd)
Use -I REPLACE
, which will replace the string REPLACE
(or whatever you pass) in the command. For example:
$ echo a b c | xargs -I {} echo before {} after
before a b c after
$ echo a b c | xargs -I REPLACE echo before REPLACE after
before a b c after
$ echo 'a
> b
> c' | xargs -L1 -I {} echo before {} after
before a after
before b after
before c after
The man page describes the option:
-I replstr
Execute utility for each input line, replacing one or more occur-
rences of replstr in up to replacements (or 5 if no -R flag is
specified) arguments to utility with the entire line of input.
The resulting arguments, after replacement is done, will not be
allowed to grow beyond replsize (or 255 if no -S flag is speci-
fied) bytes; this is implemented by concatenating as much of the
argument containing replstr as possible, to the constructed argu-
ments to utility, up to replsize bytes. The size limit does not
apply to arguments to utility which do not contain replstr, and
furthermore, no replacement will be done on utility itself.
Implies -x.
GNU xargs (e.g. on Linux)
$ echo a b c | xargs -i echo before {} after
before a b c after
$ echo a b c | xargs -I THING echo before THING after
before a b c after
Use either the -I REPLACE
or the the -i
argument, which the man page describes:
-I replace-str
Replace occurrences of replace-str in the initial-arguments
with names read from standard input. Also, unquoted blanks do
not terminate input items; instead the separator is the
newline character. Implies -x and -L 1.
-i[replace-str], --replace[=replace-str]
This option is a synonym for -Ireplace-str if replace-str is
specified. If the replace-str argument is missing, the effect
is the same as -I{}. This option is deprecated; use -I
instead.
The -L 1
on -I
means that it will execute each of the input in a separate command:
$ echo "a
> b
> c" | xargs -I THING echo before THING after
before a after
before b after
before c after
(-i
does not have this effect, though is apparently deprecated.)
回答2:
If your version of xargs doesn't include the -I
feature, an alternative is to write a little shell script containing the command you want to execute:
#!/bin/sh
exec i586-mingw32msvc-g++ "$@" -o outputFile...
Then use xargs to run that:
find . -type f -name "*.cpp" -print | xargs my_gcc_script
回答3:
You do not need xargs
for this. Just use:
g++ `find . -type f -name '*.cpp'` -o outputFile
回答4:
GNU Parallel http://www.gnu.org/software/parallel/ would be a solution too:
find . -type f -name "*.cpp" -print | parallel -X g++ {} -o outputFile
来源:https://stackoverflow.com/questions/1383170/unix-xargs-output-in-the-middle-not-at-the-end