Making xargs work in Cygwin

2019-07-20 18:20发布

Linux/bash, taking the list of lines on input and using xargs to work on each line:

% ls -1 --color=never | xargs -I{} echo {}
a
b
c

Cygwin, take 1:

$ ls -1 --color=never | xargs -I{} echo {}
    xargs: invalid option -- I
    Usage: xargs [-0prtx] [-e[eof-str]] [-i[replace-str]] [-l[max-lines]]
           [-n max-args] [-s max-chars] [-P max-procs] [--null] [--eof[=eof-str]]
           [--replace[=replace-str]] [--max-lines[=max-lines]] [--interactive]
           [--max-chars=max-chars] [--verbose] [--exit] [--max-procs=max-procs]
           [--max-args=max-args] [--no-run-if-empty] [--version] [--help]
           [command [initial-arguments]]

Cygwin, take 2:

$ ls -1 --color=never | xargs echo
a b c

(yes, I know there's a universal method of ls -1 --color=never | while read X; do echo ${X}; done, I have tested that it works in Cygwin too, but I'm looking for a way to make xargs work correctly in Cygwin)

2条回答
混吃等死
2楼-- · 2019-07-20 18:43

damienfrancois's answer is correct. You probably want to use -n to enforce echo to echo one file name at a time.

However, if you are really interested in taking each file and executing it one at a time, you may be better off using find:

$ find . -maxdepth 1 --exec echo {} \;

A few things:

  • This will pick up file names that begin with a period (including '.')
  • This will put a ./ in front of your file names.
  • The echo being used is from /bin/echo and not the built in shell version of echo.

However, it doesn't depend upon the shell executing ls * and possibility causing issues (such as coloring file names, or printing out files in sub-directories (which your command will do).

The purpose of xargs was to minimize the execution of a particular command:

$ find . -type f | xargs foo

In this case, xargs will execute foo only a minimal number of times. foo will only execute when the command line buffer gets full, or there are no more file names. However, if you are forcing an execution after each name, you're probably better off using find. It's a lot more flexible and you're not depending upon shell behavior.

查看更多
疯言疯语
3楼-- · 2019-07-20 18:46

Use the -n argument of xargs, which is really the one you should be using, as -I is an option that serves to give the argument a 'name' so you can make them appear anywhere in the command line:

$ ls -1 --color=never | xargs echo
a b c
$ ls -1 --color=never | xargs  -n 1 echo
a
b
c

From the manpage:

   -n max-args
          Use at most max-args arguments per command line

   -I replace-str
          Replace occurrences of replace-str in the initial-arguments with names read from standard input.
查看更多
登录 后发表回答