Can xargs' default delimiter be changed?

荒凉一梦 提交于 2019-12-10 02:39:46

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!