问题
I want the following behavior without having to explicitly specify it with options:
xargs -d '\n'
Unlike with most commands, you can't just use an alias because pipes don't recognize aliases (as a side-note, why is it designed this way?). I also tried creating my own ~/bin/xargs
script but I think it's not as simple as reading "$@" as a string inside the script.
Any suggestions how to make the delimiter a newline by default? I don't want to get a bunch of errors when I have a space in the path (and using find ... -print0 | xargs -0
has other unwanted effects).
UPDATE
My shell script attempt is this:
/usr/local/bin/xargs -d '\n' "$@"
回答1:
I tested xargs -d '\n' -n1 echo
on the command line and it worked as advertised; breaking the input up into single lines and echoing it.
You could be being bitten by assumptions regarding shell escaping during variable assignment. For instance, if your shell script is similar to this:
CMD="xargs -d '\n' -n1 echo"
cat inputfile | $CMD
then an error occurs, because the double-quotes around the entire CMD string preserve both the single-quotes and the backslash in the delimiter.
If you are enclosing the xargs command within quotes, you could change it to the following (no single-quotes)
CMD="xargs -d \n -n1 echo"
cat inputfile | $CMD
and it will likely function as you need.
Tested on CentOS 6.4, xargs version 4.4.2
回答2:
If your version of xargs
doesn't support setting a different delimiter (like the one on a 2011 FreeBSD server...), you can use tr
to turn your delimiters into something xargs
will work with. You might need to use a few translations before and after if your input has characters that your xargs
considers delimiters (such as spaces) or you could simply translate your delimiters to NULL
/0x0
and pass the -0
argument to xargs
.
Here is an example of using xargs
to find any file in $PATH that could be a possible shell to use (the reason I'm here, then I came up with another answer):echo $PATH | tr ':' '\0' | xargs -0 ls | grep sh | sort
回答3:
I have ~/bin
in my PATH
and keep a short script with my favorite defaults accessible by all shells on my system (at different times I use Dash, Bash, and Fish). It's tiny:
!/usr/bin/env sh
exec xargs -rd\\n "$@"
The script is called x
to avoid conflicts with scripts expecting the standard xargs
defaults. If you try to replace xargs
itself, which I don't recommend, make sure your ~/bin
appears higher in your PATH than the system xargs
. which -a xargs
tells me that the only xargs
exists at /usr/bin/xargs
in my system so I know my home directory, /home/stephen/bin
, must appear before it like so:
$ echo "$PATH"
/home/stephen/bin:...:/usr/bin:...
Either way, as a script accessible by all programs, this means you can do things like find|x grep
and sh -c 'x ...'
.
If you use Bash and prefer an alias, you can also just use:
alias x=xargs -rd\\n\ # \n delim, don't run on empty in, + alias expansion
Note the trailing space for alias expansion. This lets you chain aliases. For example, if in addition to the above alias I had an alias for grep called g
, the following would work:
# extended regex, skip binaries, devices, sockets, & dirs, colored, & line
# -buffered. use a non-canonical alias instead of GREP_OPTIONS which may wreck
# assuming scripts
alias g='grep -EID skip -d skip --color=auto --line-buffered'
$ find|x g foo
The x
/ xargs
script approach can't do this effectively by itself.
Since I switch between shells and use one PC mostly, I keep the handful of aliases I need as separate scripts in ~/bin
and shell agnostic aliases in a helper script, ~/.sh_aliases, which is sourced by ~/.shrc
, ~/.bashrc
, and ~/.config/fish/config.fish
as they all support a Bash-like alias syntax. If I worked on multiple PCs regularly, I would probably try to consolidate these into ~/.bashrc
instead.
来源:https://stackoverflow.com/questions/19204531/can-xargs-default-delimiter-be-changed